使用 pthread_mutex_lock 锁定资源是什么意思?

What does it mean to lock a resource using pthread_mutex_lock?

我是多线程的新手,我很难理解互斥。

所以这是 pthread_mutex_lock

的原型

int pthread_mutex_lock(pthread_mutex_t *mutex);

手册页说 The mutex object referenced by mutex shall be locked by calling pthread_mutex_lock().

首先我的理解是,你使用互斥锁来锁定一个共享资源,使得任何时候只有一个线程可以访问它。为了便于讨论,假设共享资源是一个名为 myVariable 的全局变量。现在如果我们要锁定myVariable,我应该可以使用锁定机制来锁定myVariable,但是锁定一个mutex object是什么意思呢?我的意思是,如果我调用 pthread_mutex_lock(&someMutex),我是在锁定 myVariable 还是其他?

总而言之,如果我想使用互斥,我难道不应该做 pthread_mutex_lock(myVariable) 之类的事情而不是 pthread_mutex_lock(&someMutex) 吗?

还有这个someMutex对象是怎么对应到myVariable的?这个 someMutex 对象如何锁定对 myVariable 的访问?

P.S。假设我已经声明了 someMutex before itself.

P.P.S。我觉得这个问题可能很宽泛,但话又说回来,这不应该是因为我问的是实际上有特定答案的问题(如果我错了请纠正我)。

someMutex基本上只是一个数值变量,不直接对应myVariable

一般顺序概念

lock(someMutex) {
    while (someMutex != 0) {}
    someMutex = 1;
}

unlock(someMutex) {
    someMutex = 0;
}

互斥量与其保护对象之间的关联不为互斥量所知,也不必如此。假设我们有两个合作的人,他们需要共用一辆车。我们不希望一个人在另一个人使用汽车时尝试使用汽车。他们可以制定一个简单的规则——除非你拿着红萝卜,否则不要乱动汽车。由于只有一个人可以拿着萝卜,这样可以确保他们在尝试使用汽车时不会相互冲突。萝卜不必知道它是 "protecting" 汽车。只要他们俩都不要管车,除非他们是拿着萝卜的人,否则萝卜会保护汽车。

互斥体就是萝卜。锁定互斥量会保持萝卜,等待其他人在需要时将其放下。解锁 mutex 将萝卜放在其他人可以得到的地方。

互斥量保护的变量或对象是汽车。萝卜保护汽车并非来自萝卜所做的任何事情,而是来自每个遵守规则的人,除非你有萝卜,否则不要碰车。互斥锁保护对象同上。

互斥锁保护一段代码,因此一次只有一个执行线程执行该区域。

互斥锁是一个基本的构建块,您有责任应用它来获得所需的结果。

如果你想改变一个共享变量,你可以这样做:

void changeit(int val)
{
    pthread_mutex_lock(&someMutex);
    global_variable = val;
    pthread_mutex_unlock(&someMutex);
}

这部分意味着一次只有 1 个线程会执行互斥量 locking/unlocking 之间的代码。这是为了确保

  • global_variable = val;正在 运行 原子地,如果2 个作业同时 运行,不能保证结果会是任何有意义的值 (不保证单个赋值语句以原子方式执行或作为 assembly/machine 代码中的 1 条指令执行)

  • 阅读 global_variable 的任何人都会在有人更改它之前或之后完全这样做,因此他们看不到任何正在更改的不一致值。

这也意味着任何其他访问(读取 and/or 写入)global_variable 的人也必须在同一互斥体被锁定时这样做,例如要读取变量,你可以这样做:

int readit(void)
{
    int val;
    pthread_mutex_lock(&someMutex);
    val = global_variable;
    pthread_mutex_unlock(&someMutex);
    return val;
}

因此,someMutex 对应于 global_variable 仅在您编写代码的方式上,它依赖于您(程序员)正确地执行它 - [= 之间没有内在联系13=] 和 someMutex

如果连接两个变量对您的程序有意义,并且必须始终一起读取或写入,则互斥量允许您这样做 - 而不是 reading/writing 上面代码所示的单个变量,你可以 read/alter 2 个变量,同时持有互斥体。同样,互斥体对这两个变量一无所知,影响全在于代码的结构。