首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么写锁挂起时可以获取读锁?

为什么写锁挂起时可以获取读锁?
EN

Stack Overflow用户
提问于 2013-05-18 06:09:51
回答 1查看 479关注 0票数 2

根据pthread_rwlock_rdlock的POSIX文档,“如果写入器不持有读锁,并且锁上没有被阻塞的写入器,则调用线程将获取读锁”。我似乎发现,即使写程序被阻塞,也可以获得读锁定。我写的一个小示例的输出如下所示:

代码语言:javascript
复制
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

对于我的代码有什么问题,或者我没有正确理解的地方,有什么建议吗?顺便说一下:

代码语言:javascript
复制
$ 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_FIFOSCHED_RR执行,那么如果编写器持有锁,则调用线程将不会获得锁……”因此,我有一个程序(如下所示),它在我的Linux系统上显示定义了_POSIX_THREAD_PRIORITY_SCHEDULING,但是我不能强制线程策略为SCHED_RR (我也尝试了SCHED_FIFO,但程序中没有显示)。

其他想法?感谢所有人..。

代码语言:javascript
复制
#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
EN

回答 1

Stack Overflow用户

发布于 2013-05-18 08:12:29

看起来像是Linux pthread实现中的一个bug。在FreeBSD上可以正常工作:

代码语言:javascript
复制
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 
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16618632

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档