the*_*mer 0 c linux multithreading mutex pthreads
我正在学习 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);
Run Code Online (Sandbox Code Playgroud)
首先这是我对互斥锁的理解:一旦我们创建了一个锁定和解锁对,这两个实体之间的代码一次只能由一个线程访问。
现在,如果我的理解是正确的,那么我几乎可以理解上述伪代码的 Writer 部分中发生的情况。我们先锁定然后写入共享资源,同时,没有人可以访问共享资源,因为它已锁定,然后我们只需将其解锁。
但我在理解读者部分时遇到了问题。如果我们锁定一次,就意味着它会永久锁定,直到我们再次解锁为止,对吗?既然如此,在读者区加锁两次有什么用呢?
我的主要问题是:锁定是什么意思?上面的伪代码中的 lock(rw_mutex) 和 lock(mutex) 有什么区别?如果一旦我们调用了一个锁,无论我们传入什么参数,程序都应该锁定它,对吗?那么这些参数:rw_mutex 和 mutex 在这里意味着什么呢?多个互斥锁如何工作?
考虑互斥体的方式是这样的:互斥体就像一个令牌,在任何时间点都可以由一个线程持有,或者可供任何线程使用。
当线程调用lock()互斥锁时,它会尝试获取互斥锁:如果互斥锁可用(“解锁”),那么它将立即获取它,否则,如果它当前由另一个线程持有(“锁定”),那么它会立即获取该互斥锁。将等到它可用。
当线程调用unlock()互斥体时,它会返回当前持有的互斥体,以便其他线程可以使用该互斥体。
如果您有多个互斥体,则每个互斥体都是独立的:一个线程可以不持有其中任何一个、一个或两个。
在您的中Reader,线程首先获取mutex. 虽然mutex为该线程所拥有,但没有其他线程可以获取,因此没有其他线程可以在任一/对mutex之间执行(一个位于函数顶部,另一个位于函数下方)。因为仅在这样的一对中被访问(当被持有时),所以我们知道一次只有一个线程会访问。lock(mutex);unlock(mutex);Readerread_countmutexread_count
如果Reader刚刚read_count从零增加到一,它也将获取rw_mutex互斥体。这可以防止任何其他线程获取该Writer互斥体,直到该互斥体被释放为止,这具有防止进入其临界区的效果。
当该线程离开临界区时,此代码有效地将 的所有权rw_mutex从锁定它的线程传递Reader给该临界区中的任何剩余读取器。这只是代码逻辑的问题 - 不需要实际调用来执行此操作(并且这只是可能的,因为它使用信号量来实现rw_mutex,而不是例如 pthreads 互斥体,它必须由锁定它的线程释放)。