pthread_rwlock_wrlock与 pthread_rwlock_rdlock区别

pthread_rwlock_t 结构体的定义:

struct
{
int __lock;
unsigned int __nr_readers;
unsigned int __readers_wakeup;
unsigned int __writer_wakeup;
unsigned int __nr_readers_queued;
unsigned int __nr_writers_queued;
/* FLAGS must stay at this position in the structure to maintain
binary compatibility. */
unsigned char __flags;
unsigned char __shared;
unsigned char __pad1;
unsigned char __pad2;
int __writer;
} __data;

在多线程编程中,死锁问题是比较难定位的一种,通过调用栈我们查看此时的pthread_rwlock_t信息,对我们定位问题的帮助是很大的。

我们通常关注的字段有:

__nr_readers,

__nr_readers_queued,

__nr_writers_queued,

__writer

那这四个字段,那当我们线程加锁时,是怎么反应并记录到这个结构体中的呢?

当我们使用pthread_rwlock_rdlock()获取一次读锁时,__nr_readers字段就会加一,注意,就算是同一个线程,在已经获得读锁的情况下,再去获取读锁,__nr_readers字段仍然会加一的,当我们调用pthread_rwlock_unlock()一次时,__nr_readers就会减一,如果我们重复加了读锁,必须重复调用pthread_rwlock_unlock()来使__nr_readers减一,否则其他线程再想获取写锁时,是会阻塞的。
2.__writer记录此时是谁占用着写锁,每一个线程都会有用同的ID号表示。

3.__nr_readers_queued和__nr_writers_queued字段表示有多少线程正等待加锁。这里有一点值得注意的地方就是,当想要获取读锁,但是发现__nr_writers_queued字段不为0,可就是有别的线程在等待获取写锁时,且该线程的优先级高于或想同于自己的优先级时,自己是无法或许读锁的,即使当前pthread_rwlock_t只是被加了读锁,但是有高优先级的线程已经在等待加写锁,自己仍然阻塞,为什么要这样呢?如果不这样,那读锁就会很有可能被一直占着,想加写锁的被饿死的情况。

如果自己已经获取了一次读锁,但是却错误的调用了两次pthread_rwlock_unlock(),会出现什么情况呢?自己在ubuntu上试了一下,__nr_readers变成了一个很大的数,也就是0又减一了,造成以后的写锁可能再也获取不了了!

如果自己已经获取了写锁,再去加读锁,pthread_rwlock_wrlock()是会返回出错的。

如果自己已经获取了读锁,再去加写锁,会出现死锁的。

读写锁是用来解决读者写者问题的,读操作可以共享,写操作是排他的,读可以有多个在读,写只有唯一个在写,同时写的时候不允许读。

具有强读者同步和强写者同步两种形式

强读者同步:当写者没有进行写操作,读者就可以访问;

强写者同步:当所有写者都写完之后,才能进行读操作,读者需要最新的信息,一些事实性较高的系统可能会用到该所,比如定票之类的。
读写锁的操作:

读写锁的初始化:

 定义读写锁:          pthread_rwlock_t  m_rw_lock;

    函数原型:              pthread_rwlock_init(pthread_rwlock_t * ,pthread_rwattr_t *);

    返回值:0,表示成功,非0为一错误码

读写锁的销毁:

函数原型:             pthread_rwlock_destroy(pthread_rwlock_t* );
返回值:0,表示成功,非0表示错误码

获取读写锁的读锁操作:分为阻塞式获取和非阻塞式获取,如果读写锁由一个写者持有,则读线程会阻塞直至写入者释放读写锁。

阻塞式:
    函数原型:pthread_rwlock_rdlock(pthread_rwlock_t*);
非阻塞式:
    函数原型:pthread_rwlock_tryrdlock(pthread_rwlock_t*);
   返回值: 0,表示成功,非0表示错误码,非阻塞会返回ebusy而不会让线程等待

获取读写锁的写锁操作:分为阻塞和非阻塞,如果对应的读写锁被其它写者持有,或者读写锁被读者持有,该线程都会阻塞等待。

 阻塞式:
      函数原型:pthread_rwlock_wrlock(pthread_rwlock_t*);
  非阻塞式:
      数原型:pthread_rwlock_trywrlock(pthread_rwlock_t*);
   返回值: 0,表示成功

释放读写锁:

函数原型:pthread_rwlock_unlock(pthread_rwlock_t*);

总结:
总结:

互斥锁与读写锁的区别:
当访问临界区资源时(访问的含义包括所有的操作:读和写),需要上斥锁;
当对数据(互斥锁中的临界区资源)进行读取时,需要上读取锁,当对数据进行写入时,需要上写入锁。
读写锁的优点:
对于读数据比修改数据频繁的应用,用读写锁代替互斥锁可以提高效率。因为使用互斥锁时,即使是读出数据(相当于操作临界区资源)都要上互斥锁,而采用读写锁,则可以在任一时刻允许多个读出者存在,提高了更高的并发度,同时在某个写入者修改数据期间保护该数据,以免任何其它读出者或写入者的干扰。
读写锁描述:
获取一个读写锁用于读称为共享锁,获取一个读写锁用于写称为独占锁,因此这种对于某个给定资源的共享访问也称为共享-独占上锁。
有关这种类型问题(多个读出者和一个写入者)的其它说法有读出者与写入者问题以及多读出者-单写入者锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值