POSIX线程中的互斥概念

时间:2011-06-17 11:21:35

标签: linux multithreading gcc posix gnu

任何人都可以告诉我如何在posix线程中使用互斥锁。 我们正在声明一个互斥锁为pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER .. 我们正在使用pthread_mutex_lock(& mutex1)来锁定关键代码。 但我的问题是它锁定了什么 我们没有指定要锁定的代码 如果我有4个线程,我希望线程1资源被锁定,我怎么能告诉编译器 我无法理解它可以帮助我们。 什么是互斥体的真正用途 等待答案..

3 个答案:

答案 0 :(得分:4)

完全取决于你自己决定,pthreads没有指明锁是做什么或不保护什么。

E.g。如果你想保护一个变量“a”,你应该确保所有对“a”的访问都是在互斥锁的保护下发生的(例如,“a_lock”)。对于一个简单的(未经测试的)示例


static int a;
static pthread_mutex_t a_lock = PTHREAD_MUTEX_INITIALIZER;

/* Add argument to static variable a in a thread-safe manner and return the result.  (In real life, for this kind of operation you could use an atomic operation) */
int increment_a(int i)
{
  int res;
  pthread_mutex_lock(&a_lock);
  a += i;
  res = a;
  pthread_mutex_unlock(&a_lock);
  return res;
}

也就是说,硬件,操作系统,线程库或其他任何内容都没有指定要保护的数据(上例中的变量“a”)和互斥锁之间的任何关系。 '用于实现所述保护(上面的互斥锁“a_lock”)。 pthread库只能确保一次只有一个线程可以保存互斥锁。

答案 1 :(得分:0)

它锁定的代码,保护,锁定和解锁之间的代码

pthread_mutex_lock(&mtx)
global_var = global_var + 10;
pthread_mutex_unlock(&mtx)

在这个简单的例子中,您要保护此全局变量的增量,这是必要的,因为递增数字的过程需要三个步骤:

  1. 从ram
  2. 中读取当前值
  3. 增加该值
  4. 将该值写回ram
  5. 让我们专注于第1步和第2步。线程CAN(并且将确保这一点)在步骤1(读取)之后立即切换,而另一个线程将读取相同的值作为第一个,因为它从来没有机会更新回到ram。当第一个线程恢复工作时(在步骤1之后),它将增加它之前读取的值并将错误的最终值写回ram,覆盖第二个线程的工作。

    换句话说:

    [Thread 1] Reads the value 10
    [Thread 2] Reads the value 10
    [Thread 2] Increments it by 5 (value is now 15)
    [Thread 2] Writes it back
    [Thread 1] Increments it by 5 **(value is now 15)**
    [Thread 1] Writes it back
    Final value: 15
    

    最终值应该是20,而不是15.看到问题? 使用互斥锁,您可以序列化访问,将内容放入正确的顺序,因此它变为

    [Thread 1] Reads the value 10
    [Thread 1] Increments it by 5 (value is now 15)
    [Thread 1] Writes it back
    [Thread 2] Reads the value 15
    [Thread 2] Increments it by 5 (value is now 20)
    [Thread 2] Writes it back
    Final value: 20
    

    如果我感到困惑,我很抱歉,但线程编程起初很困惑。花一点时间思考多线程,但在那里徘徊!这是一个非常重要的概念,特别是现在多核CPU是事实上的标准。

答案 2 :(得分:0)

线程共享内存(堆栈和可能的线程本地存储除外)。所以,你需要做一些事情来避免两个线程相互踩踏。

互斥是防止线程相互干扰的一种方法。互斥锁是一个MUTual EXClusion原语,一次只能有一个线程可以容纳给定的互斥锁。

因此,如果要保护某些数据结构不受多个线程的同时访问,则将互斥锁与该线程关联,并将对该数据结构的每次访问都包装为互斥锁和解锁调用。这样,您可以确保一次只有一个线程可以访问数据结构。

如果线程持有互斥锁,并且第二个线程试图锁定互斥锁,则第二个线程将阻塞(休眠)直到第一个线程解锁互斥锁。