我正在学习 POSIX 线程,我的教授已经开始教授第一个读写器问题。这是我关于解决问题的伪代码(仅适用于第一种情况:读者的偏好)。
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 部分中发生的情况。我们先锁定然后写入共享资源,同时,没有人可以访问共享资源,因为它已锁定,然后我们只需将其解锁即可。
但是我在理解读者部分时遇到了问题。如果我们锁定一次,就意味着它会永久锁定,直到我们再次解锁为止,对吗?既然如此,在读者区加锁两次有什么用呢?
我的主要问题是: 锁定是什么意思?上面的伪代码中的 lock(rw_mutex) 和 lock(mutex) 有什么区别?如果一旦我们调用了一个锁,无论我们传入什么参数,程序都应该锁定它,对吗?那么这些参数:rw_mutex 和 mutex 在这里意味着什么呢?多个互斥锁如何工作?
最佳答案
思考互斥体的方式是这样的:互斥体就像一个 token ,在任何时间点都可以由一个线程持有,或者可供任何线程使用。
当线程在互斥体上调用 lock()
时,它会尝试获取互斥体:如果互斥体可用(“解锁”),那么它将立即获取它,否则如果它当前由另一个线程持有(“锁定”),那么它将等待直到它可用。
当线程在互斥锁上调用 unlock()
时,它会返回当前持有的互斥锁,以便其他线程可以获取该互斥锁。
如果您有多个互斥锁,则每个互斥锁都是独立的:一个线程可以不持有它们中的任何一个、一个或两个。
在您的Reader
中,线程首先获取互斥体
。虽然 mutex
归该线程所有,但其他线程无法获取 mutex
,因此任何其他线程都无法在 的任一之间执行lock(mutex);
/unlock(mutex);
对(一对位于 Reader
函数顶部,另一对位于下方)。因为 read_count
仅在这样的一对中被访问(当 mutex
被持有)时,我们知道一次只有一个线程会访问 read_count
.
如果Reader
刚刚将read_count
从零增加到1,它还将获取rw_mutex
互斥体。这可以防止任何其他线程获取该互斥体,直到该互斥体被释放为止,从而防止 Writer
继续进入其临界区。
当该线程离开临界区时,此代码有效地将 rw_mutex
的所有权从将其锁定在 Reader
中的线程传递给该临界区中的任何剩余读取器。这只是代码逻辑的问题 - 不需要实际调用来执行此操作(并且这只是可能的,因为它使用信号量来实现 rw_mutex,而不是例如 pthreads 互斥体,它必须由锁定它的线程释放)。
关于c - 多个互斥锁如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36974246/