读/写锁在pthread中

时间:2013-10-20 20:44:20

标签: c multithreading pthreads

我正在学习pthread并遇到了读者作家锁。场景非常简单;由所有线程共享的全局变量,reader继续打印同一个全局变量的当前值,而writer将更新同一个变量。我可以通过使用两个互斥锁(pthread_mutex_t)来实现此同步,但我想使用“一个”读写器锁来实现相同的结果。但是,使用一个读写器锁,如此处所示(程序的输出,下面),读者只能看到x的第一个值,并且看不到对全局变量的任何更新。请点亮这里。

代码:

#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

     

父进程看到x:3

1 个答案:

答案 0 :(得分:7)

当一个线程获得一个锁时,其他试图获取同一个锁的线程将被挂起,直到第一个线程释放锁。

这里发生的是你的读者线程开始,获取锁定,并进入for/poll循环。

编写器线程启动,尝试获取读取器线程已经占用的锁,并在pthread_rwlock_wrlock上保持阻塞状态。

您实际想要做的是在访问共享变量的代码之前和之后放置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);