读写锁

索引:

  1. 初始化一个读写锁pthread_rwlock_init
  2. 读锁定读写锁      pthread_rwlock_rdlock
  3. 非阻塞读锁定  pthread_rwlock_tryrdlock
  4. 写锁定读写锁      pthread_rwlock_wrlock
  5. 非阻塞写锁定      pthread_rwlock_trywrlock
  6. 解锁读写锁         pthread_rwlock_unlock
  7. 释放读写锁         pthread_rwlock_destroy

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

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

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

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

1.初始化一个读写锁pthread_rwlock_init

#include <pthread.h>

  int pthread_rwlock_init(pthread_rwlock_t *rwlock, \ const pthread_rwlockattr_t *attr);

  返回值:函数成功返回0;任何其他返回值都表示错误

初始化rwlock指定的读写锁,它的属性被参数attr指定。如果attr的值为NULL,初始化读写锁时使用缺省的读写锁属性。其效果和attr指向一个缺省的读写锁属性对象是一样的。

成功初始化后,读写锁的状态为非锁定的。

对一个已经初始化过的读写锁调用pthread_rwlock_init函数会产生不可预测的后果。使用一个未经初始化的读写锁也会产生不可预测的后果。

如果需要缺省属性的读写锁,可以用宏PTHREAD_RWLOCK_INITIALIZER初始化静态的读写锁变量。但是,静态初始化读写锁不进行错误检查。如:

pthread_rwlock_t rwlock = PTHREASD_RWLOCK_INITIALIZER;

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

2.读锁定读写锁pthread_rwlock_rdlock

  #include <pthread.h>

  int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

  返回值:函数成功返回0;任何其他返回值都表示错误

函数在rwlock读写锁上进行读锁定。

如果一个线程写锁定了读写锁,调用pthread_rwlock_rdlock函数的线程将无法读锁定读写锁,并将被阻塞,直到线程可以读锁定这个读写锁为止。

如果一个线程写锁定了读写锁后又调用pthread_rwlock_rdlock函数来读锁定同一个读写锁,结果将无法预测。

标准中没有指定当没有线程写锁定这个读写锁,但有线程试图写锁定而被阻塞在这个读写锁上时,当前线程是否能读锁定读写锁。大多数线程库往往优先考虑激活试图写锁定而被阻塞的线程,这样做是为了防止试图写锁定而被阻塞的线程长时间得不到调度。

一个线程可能对一个读写锁进行了多次读锁定(即成功调用了pthread_rwlock_rdlock()函数多次)。如果是这样的,线程必须调用pthread_rwlock_unlock()函数对读写锁进行同样次数的解锁。

当一个读写锁被读锁定了,而一个线程阻塞在这个读写锁上时,如果这时来了一个信号,那么当线程从信号处理程序中返回时,将继续阻塞在这个读写锁上。就好象线程没有被中断过。

3.非阻塞读锁定pthread_rwlock_tryrdlock

  #include <pthread.h>

  int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

  返回值:函数成功返回0;任何其他返回值都表示错误

pthread_rwlock_tryrdlock()函数和pthread_rwlock_rdlock函数的功能相近,不同的是,当已有线程写锁定读写锁,或是有试图写锁定的线程被阻塞时,pthread_rwlock_tryrdlock函数失败返回。

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

4.写锁定读写锁pthread_rwlock_wrlock

  #include <pthread.h>

  int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

  返回值:函数成功返回0;任何其他返回值都表示错误

写锁定读写锁rwlock。如果没有线程读或写锁定读写锁rwlock,当前线程将写锁定读写锁rwlock。否则线程将被阻塞,直到没有线程锁定这个读写锁为止。

如果调用这个函数之前,本线程已经读或写锁定了这个读写锁,那么pthread_rwlock_wrlock函数运行的结果是不可预测的。

读写锁被解开以后,激活阻塞在读写锁上的线程时,往往优先考虑试图写锁定而被阻塞的线程,这样做是为了防止试图写锁定而被阻塞的线程长时间得不到调度。

当一个读写锁被写锁定了,而一个线程阻塞在这个读写锁上时,如果这时来了一个信号,那么当线程从信号处理程序中返回时,将继续阻塞在这个读写锁上。就好像线程没有被中断过。

5.非阻塞写锁定pthread_rwlock_trywrlock

  #include <pthread.h>

  int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

  返回值:函数成功返回0;任何其他返回值都表示错误

pthread_rwlock_trywrlock函数的功能和pthread_rwlock_wrlock函数相近。不同的是如果有其他线程锁定了读写锁,pthread_rwlock_trywrlock函数会失败返回。

6.解锁读写锁pthread_rwlock_unlock

  #include <pthread.h>

  int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

  返回值:函数成功返回0;任何其他返回值都表示错误

解锁一个读写锁。

调用pthread_rwlock_unlock函数之前必须调用pthread_rwlock_rdlock函数或pthread_rwlock_wrlock函数锁定读写锁。否则结果是不可预测的。

在pthread_rwlock_unlock函数被用来解锁对读写锁的读锁定后,如果本线程对这个读写锁还有其他读锁定,那么这个读写锁对本线程将继续保持读锁定状态。如果pthread_rwlock_unlock函数解开了当前线程在这个读写锁上的最后一个读锁定,那么当前线程将不再拥有对这个读写锁的读锁定。如果pthread_rwlock_unlock函数解开了这个读写锁上的最后一个锁定,那么这个读写锁将处在非锁定状态。

如果pthread_rwlock_unlock函数被用来解锁对读写锁的写锁定,那么函数返回后,这个读写锁将处在非锁定状态。

如果用pthread_rwlock_unlock函数解锁一个读写锁时,有多个线程在等待对这个读写锁进行写锁定,系统将用调度策略决定激活哪个线程对读写锁进行写锁定。

如果用pthread_rwlock_unlock函数解锁一个读写锁时,有多个线程在等待对这个读写锁进行读锁定,系统将用调度策略决定按什么顺序激活各个线程对读写锁进行读锁定。

如果用pthread_rwlock_unlock函数解锁一个读写锁时,有多个线程在等待对这个读写锁进行写锁定和读锁定,一般先激活需要写锁定的线程对读写锁进行写锁定(标准没有指定在这种情况下应该先激活写线程还是先激活读线程)。

7.释放读写锁pthread_rwlock_destroy

  #include <pthread.h>

  int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

  返回值:函数成功返回0;任何其他返回值都表示错误

释放读写锁rwlock,并释放这个读写锁占用的资源。一般情况下,pthread_rwlock_destroy函数将rwlock指向的互斥锁对象设置为非法值。

释放了一个读写锁之后,在pthread_rwlock_init重新初始化它之前,再使用这个读写锁会有不可预料的结果。

如果有线程锁定了某个读写锁,那么用pthread_rwlock_destroy()函数释放这个读写锁会引起不可预知的结果。

试图释放一个未初始化的读写锁会引起不可预知的结果。

总结(转):

互斥锁与读写锁的区别:

当访问临界区资源时(访问的含义包括所有的操作:读和写),需要上互斥锁;

当对数据(互斥锁中的临界区资源)进行读取时,需要上读取锁,当对数据进行写入时,需要上写入锁。

读写锁的优点:

对于读数据比修改数据频繁的应用,用读写锁代替互斥锁可以提高效率。因为使用互斥锁时,即使是读出数据(相当于操作临界区资源)都要上互斥锁,而采用读写锁,则可以在任一时刻允许多个读出者存在,提高了更高的并发度,同时在某个写入者修改数据期间保护该数据,以免任何其它读出者或写入者的干扰。

读写锁描述:

获取一个读写锁用于读称为共享锁,获取一个读写锁用于写称为独占锁,因此这种对于某个给定资源的共享访问也称为共享-独占上锁。

有关这种类型问题(多个读出者和一个写入者)的其它说法有读出者与写入者问题以及多读出者-单写入者锁。

pthread_rwlock_t读写锁函数说明的更多相关文章

  1. UNIX环境高级编程——线程同步之读写锁以及属性

    读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 互 ...

  2. Linux 读写锁

    线程的读写锁函数: 1,读写锁的初始化与销毁,静态初始化的话,可以直接使用PTHREAD_RWLOCK_INITIALIZER. #include <pthread.h> int pthr ...

  3. pthread 读写锁

    pthread 读写锁 (Read Write Lock, rwlock) 把对共享资源的访问者分为读者和写者,读者仅仅对共享资源进行读访问,写者仅仅对共享资源进行写操作. 如果使用互斥量 mutex ...

  4. Linux线程同步之读写锁(rwlock)

    读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 和 ...

  5. freeswitch APR库线程读写锁

    概述 freeswitch的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性. 线程读写锁在多线程服务中有重要的作用.对于读数据比写数据频繁的服务,用读写锁代替互斥锁可以提高效率. 由于A ...

  6. 读者写者问题继 读写锁SRWLock

    在<秒杀多线程第十一篇读者写者问题>文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法--读写锁SRWLock来解决这一 ...

  7. 多线程面试题系列(14):读者写者问题继 读写锁SRWLock

    在第十一篇文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法--读写锁SRWLock来解决这一问题.读写锁在对资源进行保护的同时,还 ...

  8. 转---秒杀多线程第十四篇 读者写者问题继 读写锁SRWLock

    在<秒杀多线程第十一篇读者写者问题>文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法——读写锁SRWLock来解决这一 ...

  9. 多线程 读写锁SRWLock

    在<秒杀多线程第十一篇读者写者问题>文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法——读写锁SRWLock来解决这一 ...

随机推荐

  1. ServiceStack.Redis 之 IRedisTypedClient

    IRedisTypedClient IRedisTypedClient类相当于IRedicClient的强类型版,其方法与属性大多数与IRedisClient类似. 它支持在Redis中使用Linq查 ...

  2. once

    var once = function(obj, evtType, handler) { var f = function() { //console.log(arguments) handler.a ...

  3. 【转】 学习ios(必看经典)牛人40天精通iOS开发的学习方法【2015.12.2

    原文网址:http://bbs.51cto.com/thread-1099956-1.html 亲爱的学员们: 如今,各路开发者为淘一桶金也纷纷转入iOS开发的行列.你心动了吗?想要行动吗?知道如何做 ...

  4. 水题:HDU 5112 A Curious Matt

    Description There is a curious man called Matt. One day, Matt's best friend Ted is wandering on the ...

  5. Java GC专家系列2:Java 垃圾回收的监控

    这是”成为GC专家系列”文章的第二篇.在第一篇理解Java垃圾回收中我们学习了几种不同的GC算法的处理过程,GC的工作方式,新生代与老年代的区别.到目前为止,你应该已经了解了JDK 7中的5种GC类型 ...

  6. runtime/KVO等面试题

    整理中... 1.KVO内部实现原则 回答:1>KVO是基于runtime机制实现的 2>当某个类的对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中 ...

  7. 390. Elimination Game

    正规解法直接跳到代码上面一点的部分就可以了.但我想记录下自己的思考和尝试过程,希望二刷能看到问题所在. 找规律的时候写了好多,虽然规律很简单. 只要随便写3以上的例子,就应该发现,相邻的2个最后结果是 ...

  8. Android之打开闪光灯关键代码

    在AndroidManifest中注册相应的权限: <uses-permission android:name="android.permission.FLASHLIGHT" ...

  9. MFC——error LNK2005: "protected: static struct AFX_MSGMAP

    好久没弄VC程序了,今天弄了下,还会用公司给的窗口重绘作为基类来实现,竟然报了这个错误. 找了一下是这里: 有个窗口重绘类是基类: class CBaseDlg : public CDialog 新建 ...

  10. Qt 学习之路 :菜单栏、工具栏和状态栏

    在之前的<添加动作>一文中,我们已经了解了,Qt 将用户与界面进行交互的元素抽象为一种“动作”,使用QAction类表示.QAction可以添加到菜单上.工具栏上.期间,我们还详细介绍了一 ...