多重互斥锁是如何工作的?

How do multiple mutex locks work?

我正在学习 POSIX 线程,我的教授已经开始教授第一个 readers-writers 问题。这是我解决问题的伪代码(仅适用于第一种情况:reader 的偏好)。

semaphore rw_mutex = 1; /* semaphore common to both reader & writer */
semaphore mutex = 1; /* semaphore for reading (reader lock) */
int read_count = 0; /* track number of readers in CS */


Writer:
do {
lock(rw_mutex);
/* ensure no writer or reader can enter */
...
/* writing is performed */
...
unlock(rw_mutex);
/* release lock */
} while (true);


Reader:
do
{
lock(mutex);
/* first update read_count atomically */
read_count++;
if (read_count == 1) {
lock(rw_mutex);
/* ensure no writer can enter */
}
unlock(mutex);
/* allow other readers to access */
...
/* reading is performed */
...
lock(mutex);
read_count--;if (read_count == 0) unlock(rw_mutex);
/* allow writers after
last reader has left the CS */
unlock(mutex);
/* release lock */
} while(true);

首先这是我对互斥锁的理解:一旦我们创建了锁和解锁对,这两个实体之间的代码一次只能由一个线程访问。

现在,如果我的理解是正确的,那么我几乎可以理解上述伪代码的 Writer 部分发生了什么。我们锁定然后写入共享资源,与此同时,没有人可以访问共享资源,因为它被锁定,然后我们简单地解锁它。

但是我在理解 reader 部分时遇到问题。如果我们锁定一次,这意味着它一直处于锁定状态,直到我们再次解锁它,对吗?在那种情况下,在 reader 的部分中锁定两次有什么用?

我的主要问题是: 锁定是什么意思?上面伪代码中的 say lock(rw_mutex) 和 lock(mutex) 有什么区别?如果我们一旦调用锁,程序就应该锁定它,而不管我们传入什么参数,对吗?那么这些参数:rw_mutex 和 mutex 在这里意味着什么?多互斥锁是如何工作的?

互斥锁的思考方式是这样的:互斥锁就像一个令牌,在任何时间点都可以由一个线程持有,或者可供任何线程使用。

当线程在互斥量上调用 lock() 时,它正在尝试获取互斥量:如果互斥量可用 ("unlocked") 则它会立即获取它,否则如果可用当前由另一个线程 ("locked") 持有,然后它将等待直到它可用。

当线程调用互斥体上的 unlock() 时,它会返回它当前持有的互斥体,以便另一个线程可以使用它。

如果您有多个互斥量,则每个互斥量都是独立的:一个线程可以不包含其中一个,也可以包含一个或两个。

在您的 Reader 中,线程首先获取 mutex。虽然 mutex 由线程拥有,但没有其他线程可以获取 mutex,因此没有其他线程可以在 lock(mutex);either 之间执行 / unlock(mutex); 对(一对在 Reader 函数的顶部,另一对在下方)。因为 read_count 只会在这样的一对中被访问(而 mutex 被保留),我们知道一次只有一个线程会访问 read_count

如果 Reader 刚刚将 read_count 从零递增到一,它也会获得 rw_mutex 互斥量。这可以防止任何其他线程获取 that 互斥锁,直到它被释放,这具有防止 Writer 进入其临界区的效果。

当线程离开临界区时,此代码有效地将 rw_mutex 的所有权从将它锁定在 Reader 中的线程传递给临界区中的任何剩余读者。这只是代码逻辑的问题 - 不需要实际调用来执行此操作(这只是可能的,因为它使用信号量来实现 rw_mutex,而不是例如 pthreads 互斥锁,它必须由锁定它的线程)。