1

我有以下通过线程执行的示例代码(请参见下面的代码):

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.

基本上读锁是递归的。它是 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;
}
4

2 回答 2

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

于 2012-01-10T14:13:39.657 回答
0

是的,在 rwlock 上的锁是读锁,在某种程度上确实是递归的。但是POSIX 文档中pthread_rwlock_rdlock有一行, SUSv2 因为这是 Apple 所支持的:

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

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

Apple 自己的在线文档也支持这一点:

pthread_rwlock_rdlock() 函数在 rwlock 上获得一个读锁,前提是 rwlock 目前没有被持有以进行写入,并且目前没有写入器线程在锁上被阻塞。

然后:

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

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

于 2012-01-10T14:18:39.627 回答