2

pthread_rwlock_rdlock の POSIX ドキュメントによると、「ライターがロックを保持しておらず、ロックでブロックされているライターがない場合、呼び出しスレッドは読み取りロックを取得します。」ライターがブロックされている場合でも、読み取りロックを取得できることがわかったようです。私が書いた小さなサンプルの出力は次のようになります。

first reader acquiring lock...
first reader lock acquired
first writer acquiring lock...
second reader acquiring lock...
second reader lock acquired
first reader releasing lock
second reader releasing lock
first writer lock acquired
first writer releasing lock

私のコードのどこが間違っているか、または私が正しく理解していないことについて何か提案はありますか? ところで:

$ make
gcc -g -I. -I../../isilib -c -Wpointer-arith -Wall -pedantic-errors
-D_POSIX_C_SOURCE=200809L -std=c99 -g rwlock_test1.c -o rwlock_test1.o
gcc rwlock_test1.o -L../../isilib -lisi -lrt -lm -pthread -o rwlock_test1
$ uname -a
Linux BLACKHEART 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 
2012 x86_64 x86_64 x86_64 GNU/Linux
$ gcc --version
gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2

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

#define PTH_create( a, b, c, d ) \
    (pthread_create( (a), (b), (c), (d) ) != 0 ? abort() : (void)0 )

#define PTH_join( a, b ) \
    (pthread_join( (a), (b) ) != 0 ? abort() : (void)0 )

#define PTH_rwlock_rdlock( a ) \
    (pthread_rwlock_rdlock( (a) ) != 0 ? abort() : (void)0 )

#define PTH_rwlock_wrlock( a ) \
    (pthread_rwlock_wrlock( (a) ) != 0 ? abort() : (void)0 )

#define PTH_rwlock_unlock( a ) \
    (pthread_rwlock_unlock( (a) ) != 0 ? abort() : (void)0 )

static void *firstReader(
    void *arg
);

static void *firstWriter(
    void *arg
);

static void *secondReader(
    void *arg
);

static pthread_rwlock_t rwlock  = PTHREAD_RWLOCK_INITIALIZER;

int main( int argc, char **argv )
{
    pthread_t   thr1;
    pthread_t   thr2;
    pthread_t   thr3;

    PTH_create( &thr1, NULL, firstReader, NULL );
    PTH_create( &thr2, NULL, firstWriter, NULL );
    PTH_create( &thr3, NULL, secondReader, NULL );

    PTH_join( thr1, NULL );
    PTH_join( thr2, NULL );
    PTH_join( thr3, NULL );

    return 0;
}

static void *firstReader( void *arg )
{
    printf( "first reader acquiring lock... \n" );
    PTH_rwlock_rdlock( &rwlock );
    printf( "first reader lock acquired \n" );
    sleep( 10 );
    printf( "first reader releasing lock \n" );
    PTH_rwlock_unlock( &rwlock );
    return NULL;
}

static void *firstWriter( void *arg )
{
    sleep( 2 );
    printf( "first writer acquiring lock... \n" );
    PTH_rwlock_wrlock( &rwlock );
    printf( "first writer lock acquired \n" );
    sleep( 10 );
    printf( "first writer releasing lock \n" );
    PTH_rwlock_unlock( &rwlock );
    return NULL;
}

static void *secondReader( void *arg )
{
    sleep( 5 );
    printf( "second reader acquiring lock... \n" );
    PTH_rwlock_rdlock( &rwlock );
    printf( "second reader lock acquired \n" );
    sleep( 5 );
    printf( "second reader releasing lock \n" );
    PTH_rwlock_unlock( &rwlock );
    return NULL;
}

追加情報:

posix 標準から: マクロ_POSIX_THREAD_PRIORITY_SCHEDULINGは、スレッド実行スケジューリング オプションがサポートされているかどうかを示します。からunistd.h:「これらのシンボルが定義されている場合、対応する機能は常に利用可能です...」そしてリスト_POSIX_THREAD_PRIORITY_SCHEDULING。再びposixから:「スレッド実行スケジューリングオプションがサポートされており、ロックに関与するスレッドがスケジューリングポリシーSCHED_FIFOまたはSCHED_RRで実行されている場合、ライターがロックを保持している場合、呼び出しスレッドはロックを取得しません... .」そのため、定義されているLinuxシステムで表示されるプログラム(以下)がありますが_POSIX_THREAD_PRIORITY_SCHEDULING、スレッドポリシーを強制することはできませんSCHED_RR(私も試しSCHED_FIFOましたが、プログラムには表示されていません)。

追加の考え?ありがとうございます...

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

#define PTH_create( a, b, c, d ) \
    (pthread_create( (a), (b), (c), (d) ) != 0 ? abort() : (void)0 )

#define PTH_join( a, b ) \
    (pthread_join( (a), (b) ) != 0 ? abort() : (void)0 )

static void *driver(
    void *arg
);

int main( int argc, char **argv )
{
    pthread_attr_t  attr;
    pthread_attr_init( &attr );
    pthread_attr_setschedpolicy( &attr, SCHED_RR );

    pthread_t   thrID;

    PTH_create( &thrID, &attr, driver, NULL );
    printf( "%ld\n", _POSIX_THREAD_PRIORITY_SCHEDULING );
    struct sched_param  param;
    int                 policy;
    pthread_getschedparam( thrID, &policy, &param );
    if ( policy == SCHED_FIFO )
        puts( "SCHED_FIFO" );
    else if ( policy == SCHED_RR )
        puts( "SCHED_RR" );
    else if ( policy == SCHED_FIFO )
        puts( "SCHED_FIFO" );
    else if ( policy == SCHED_OTHER )
        puts( "SCHED_OTHER" );
    else
        puts( "eh?" );

    PTH_join( thrID, NULL );

    return 0;
}

static void *driver( void *arg )
{
    sleep( 2 );
    return NULL;
}

$ ./sched_test
200809
SCHED_OTHER
4

3 に答える 3

3

あなたはPOSIXでこの文を逃しました:

スレッド実行スケジューリング オプションがサポートされていない場合、ライターがロックを保持しておらず、ロックでブロックされているライターが存在する場合に、呼び出しスレッドがロックを取得するかどうかは実装定義です。

リーダーよりもライターを優先する POSIX rwlocks に頼ることはできません。

于 2013-05-19T11:03:01.223 に答える
2

Linux pthreads 実装のバグのようです。FreeBSD で正しく動作します:

first reader acquiring lock... 
first reader lock acquired 
first writer acquiring lock... 
second reader acquiring lock... 
first reader releasing lock 
first writer lock acquired 
first writer releasing lock 
second reader lock acquired 
second reader releasing lock 
于 2013-05-18T00:12:29.497 に答える