簡體   English   中英

在Mac OS X / Darwin上遞歸pthread_rwlock_rdlock

[英]Recursive pthread_rwlock_rdlock on Mac OS X/Darwin

我有以下由線程執行的示例代碼(請參見下面的代碼):

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;
}

僅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

是的,這些鎖是rwlock上的讀取鎖,實際上是遞歸的,直到一定程度。 但是POSIX文檔中有一行關於pthread_rwlock_rdlock ,SUSv2的,因為這是Apple支持的:

如果寫入者未持有該寫入者並且鎖上沒有任何寫入者,則調用線程將獲得讀取鎖定。 當寫程序不持有該鎖並且有寫程序正在等待該鎖時,調用線程是否獲得了該鎖尚不確定。

根本沒有讓具有現有讀取鎖的線程重新鎖定以進行讀取的任何操作。 只是如果寫作者被阻止,讀鎖定請求就會被阻止(實現通常會優先選擇寫鎖定,以避免寫者餓死)。

蘋果自己的在線文檔也支持此功能:

pthread_rwlock_rdlock()函數獲取rwlock上的讀鎖,條件是當前不持有rwlock進行寫操作,並且當前沒有任何寫程序線程被阻塞。

然后:

為了防止作家飢餓,作家比讀者受寵。

再次。 沒有提到在隊列中有寫鎖時允許遞歸讀鎖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM