Mac OS X / Darwin上的递归pthread_rwlock_rdlock

时间:2012-01-10 14:01:28

标签: macos pthreads rwlock

我有以下示例代码(请参阅下面的代码),它由线程执行:

A: rd-lock
B: wr-lock (waiting)
A: rd-lock (recursive)
A: rd-unlock (recursive)
A: rd-unlock
B: wr-locked (wake after wait)
B: wr-unlock.

基本上,read-lock是递归的。它是POSIX标准所要求的(要求读锁是递归的,但没有为写锁指定)。这有效 在Linux,FreeBSD,Solaris上,但它不适用于Darwin / Mac OS X.

以下示例在Linux上提供以下输出:

read locking
read locked
write locking
read locking 2
read locked 2
read unlocked 2
read unlocked
write locked
write unlocked 2

在达尔文上打印时:

read locking
read locked
write locking
read locking 2

这里的死锁(不会继续),基本上它不尊重递归读锁。

是否可以按预期工作(标记,定义,链接特殊库版本)?


示例代码

#include <pthread.h>
#include <stdio.h>

pthread_rwlock_t lock;

void *thread_r(void *p)
{
    printf("read locking\n");
    pthread_rwlock_rdlock(&lock);
    printf("read locked\n");
    usleep(500*1000);
    printf("read locking 2\n");
    pthread_rwlock_rdlock(&lock);
    printf("read locked 2\n");
    usleep(500*1000);
    pthread_rwlock_unlock(&lock);
    printf("read unlocked 2\n");
    usleep(500*1000);
    pthread_rwlock_unlock(&lock);
    printf("read unlocked\n");
}

void *thread_w(void *p)
{
    usleep(250*1000);
    printf("write locking\n");
    pthread_rwlock_wrlock(&lock);
    printf("write locked\n");
    pthread_rwlock_unlock(&lock);
    printf("write unlocked 2\n");
}

int main()
{
    pthread_t a,b;
    pthread_rwlock_init(&lock,NULL);
    pthread_create(&a,NULL,thread_r,0);
    pthread_create(&b,NULL,thread_w,0);
    pthread_join(a,NULL);
    pthread_join(b,NULL);
    return 0;
}

2 个答案:

答案 0 :(得分:1)

只有rdlock()支持递归锁定:

http://pubs.opengroup.org/onlinepubs/007908799/xsh/pthread_rwlock_rdlock.html

根据Unix规范,如果线程已经拥有读或写锁,则调用wrlock()的行为是不确定的:

http://pubs.opengroup.org/onlinepubs/007908799/xsh/pthread_rwlock_trywrlock.html

当您使用OS X时,请查看NSRecursiveLock:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html

答案 1 :(得分:0)

是的,锁是rwlocks上的读锁确实是递归的,直到某一点。但是POSIX docs for pthread_rwlock_rdlock,SUSv2中有一条线,因为这是Apple支持的:

  

如果编写器没有锁定并且锁上没有写入器被阻塞,则调用线程获取读锁定。当编写器没有持有锁并且有编写者等待锁时,调用线程是否获取锁是未指定的。

没有任何关于让现有读锁的线程重新锁定以进行读取的内容。只是如果写入器被阻塞,读取锁定请求将被阻塞(实现通常优先考虑写入锁定以避免写入者饥饿)。

Apple's own online docs也支持这一点:

  

pthread_rwlock_rdlock()函数获取rwlock的读锁定,前提是当前没有写入rwlock进行写入,并且当前没有锁定写入器线程。

后来:

  

为了防止作家饥饿,作家比读者更受青睐。

再次。没有提到在写入锁定在队列中时允许递归读锁定。