C语言 pthread 中的读/写锁
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19482648/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
reader/writer lock in pthread
提问by Amit
I'm learning pthread and came across reader writer lock. The scenario is very simple; a global variable being shared by all the threads, reader keeps printing the current value of that same global variable, while writer will update the same variable. I can achieve this synchronization by using two mutexes (pthread_mutex_t), but I want to use "one" reader-writer lock for achieving this same result. However, with one reader-writer lock, as can be seen here(output of the program, below), reader only sees the first value of x and doesn't sees any updates to the global variable. Please throw some light here.
我正在学习 pthread 并遇到了读写锁。场景非常简单;一个被所有线程共享的全局变量,reader 不断打印同一个全局变量的当前值,而 writer 将更新同一个变量。我可以通过使用两个互斥锁 (pthread_mutex_t) 来实现这种同步,但我想使用“一个”读写锁来实现相同的结果。然而,使用一个读写器锁,正如可以在这里看到的(程序的输出,下面),读者只能看到 x 的第一个值,而看不到全局变量的任何更新。请在这里放一些光。
Code:
代码:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
#include <poll.h>
#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
int x = 0;
pthread_rwlock_t lock_rw = PTHREAD_RWLOCK_INITIALIZER;
void *reader_thread(void *arg)
{
int i;
int newx, oldx;
newx = oldx = -1;
pthread_rwlock_t *p = (pthread_rwlock_t *)arg;
if (pthread_rwlock_rdlock(p) != 0) {
perror("reader_thread: pthread_rwlock_rdlock error");
exit(__LINE__);
}
for (i = 0; i < 100; i++) {
newx = ACCESS_ONCE(x);
if (newx != oldx) {
printf("reader_lock: x: %d\n",x);
}
oldx = newx;
poll(NULL, 0, 1);
}
if (pthread_rwlock_unlock(p) != 0) {
perror("reader thread: pthred_rwlock_unlock error");
exit(__LINE__);
}
return NULL;
}
void *writer_thread(void *arg)
{
int i;
pthread_rwlock_t *p = (pthread_rwlock_t *)arg;
if (pthread_rwlock_wrlock(p) != 0) {
perror("writer thread: pthread_rwlock_wrlock error");
exit(__LINE__);
}
for (i = 0; i < 3; i++) {
ACCESS_ONCE(x)++;
poll(NULL, 0, 5);
}
if (pthread_rwlock_unlock(p) != 0) {
perror("writer thread: pthread_rwlock_unlock error");
exit(__LINE__);
}
return NULL;
}
int main(void)
{
pthread_t tid1, tid2;
void *vp;
if (pthread_create(&tid1, NULL, reader_thread, &lock_rw) != 0) {
perror("pthread_create error");
exit (__LINE__);
}
if (pthread_create(&tid2, NULL, writer_thread, &lock_rw) != 0) {
perror("pthread_create error");
exit (__LINE__);
}
//wait for the thread to complete
if (pthread_join(tid1, &vp) != 0) {
perror("pthread_join error");
exit (__LINE__);
}
if (pthread_join(tid2, &vp) != 0) {
perror("pthread_join error");
exit (__LINE__);
}
printf("Parent process sees x: %d\n",x);
return 0;
}
gcc pthread_rwlock.c -o rwlock -pthread -Wall -Werror
./rwlock
reader_lock: x: 0
Parent process sees x: 3
gcc pthread_rwlock.c -o rwlock -pthread -Wall -Werror
./rwlock
reader_lock: x: 0
父进程看到 x: 3
回答by Flavio
When a thread acquires a lock, other threads trying to acquire the same lock will be suspended until the first thread releases the lock.
当一个线程获取锁时,其他试图获取相同锁的线程将被挂起,直到第一个线程释放锁。
What is happening here is that your reader thread starts, acquires the lock, and enters the for/pollloop.
这里发生的事情是你的阅读器线程启动,获取锁,然后进入for/poll循环。
The writer thread starts, tries to acquire the lock which was already taken by the reader thread, and remains blocked on pthread_rwlock_wrlock.
写入器线程启动,尝试获取已被读取器线程占用的锁,并在 上保持阻塞状态pthread_rwlock_wrlock。
What you actually want to do is to put your lock/unlockright before and after the code where you access your shared variable.
您真正想要做的是将您的lock/unlock权利放在访问共享变量的代码之前和之后。
thread_rwlock_rdlock(p);
newx = ACCESS_ONCE(x);
thread_rwlock_unlock(p);
...
thread_rwlock_wrlock(p);
ACCESS_ONCE(x)++;
thread_rwlock_unlock(p);

