c - 多个互斥锁如何工作?

标签 c linux multithreading pthreads mutex

我正在学习 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/

相关文章:

php - 如何将 PHP 数组传递给 BASH 脚本?

c# - 使用仅包含静态方法而不包含变量的 C# 类时会出现并发问题吗?

c++ - 增加进程的内存使用

multithreading - 多线程 : what am I missing? 随着时间的推移性能严重下降

c - 嵌入 Lua 5.2 和定义库

c - Google 自定义搜索结果 C 语言

linux - 如何让 ubuntu 软件中心知道我的 debian 文件

java - 通过 java 代码编译 C 源代码

python - 使用 Ctypes 从 Python 传递 C 结构指针

linux - Ubuntu 16.04 登录循环