pthread中的读取器/写入器锁定 [英] reader/writer lock in pthread
问题描述
我正在学习pthread,并遇到读者写作者锁.场景非常简单;一个由所有线程共享的全局变量,读取器将继续打印该相同全局变量的当前值,而写入器将更新同一变量.我可以通过使用两个互斥对象(pthread_mutex_t)来实现这种同步,但是我想使用一个"读写器锁来实现相同的结果.但是,使用一个读写器锁(如此处所示(程序的输出,在下面)),读者只能看到x的第一个值,而看不到全局变量的任何更新.请在这里放些灯光.
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.
代码:
#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
gcc pthread_rwlock.c -o rwlock -pthread -Wall -Werror
./rwlock
reader_lock:x:0
reader_lock: x: 0
父进程看到x:3
推荐答案
当一个线程获取一个锁时,试图获取相同锁的其他线程将被挂起,直到第一个线程释放该锁为止.
When a thread acquires a lock, other threads trying to acquire the same lock will be suspended until the first thread releases the lock.
这里发生的是您的阅读器线程启动,获取锁并进入for/poll
循环.
What is happening here is that your reader thread starts, acquires the lock, and enters the for/poll
loop.
写程序线程启动,尝试获取读线程已获取的锁,并在pthread_rwlock_wrlock
上保持阻塞.
The writer thread starts, tries to acquire the lock which was already taken by the reader thread, and remains blocked on pthread_rwlock_wrlock
.
您真正想要做的是将lock/unlock
放在访问共享变量的代码之前和之后.
What you actually want to do is to put your lock/unlock
right before and after the code where you access your shared variable.
thread_rwlock_rdlock(p);
newx = ACCESS_ONCE(x);
thread_rwlock_unlock(p);
...
thread_rwlock_wrlock(p);
ACCESS_ONCE(x)++;
thread_rwlock_unlock(p);
这篇关于pthread中的读取器/写入器锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!