pthread_rwlock_t读写锁函数说明

读写锁

索引:

  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读写锁函数说明

时间: 2024-08-13 17:06:57

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

Windows Vista新增的读写锁函数

Windows Vista及更新的Windows客户端系统,Windows Server 2008及更新的Windows服务器系统,新增了读写锁API函数,我们不用再手动编写读写锁了. 要使用读写锁,当然要包含Windows头文件,并定义一个SRWLOCK(结构体)类型的变量: SRWLOCK Lock; SRWLOCK类型的变量,不能手动赋值,不能取其中字段的值,也不能用memcpy等函数拷贝它所占的内存,对它的所有操作(初始化.读锁.写锁等等)只能通过相关的函数来进行. 初始化读写锁的函数是

读写锁————用互斥量和条件变量模拟

一. 读写锁 在多线程环境下为了防止对临界资源访问的冲突我们往往会在线程函数中加入互斥锁来完成线程间的互斥:但是,在有些情况下,互斥锁mutex并不是那么高效,比如当要对一块缓冲区进行读写操作的时候,因为读的需要比写入修改的需要要多,读取数据并不会修改缓冲区的数据个数或者内容,如果要使用互斥锁就会耗费额外的时间,每一次读取都要争夺锁资源挂起等待,因此就可以使用另外一种锁机制----读写锁. 有读写锁的存在当然就会有读者和写者,也就是多个线程,但是它们之间的相互关系和mutex锁中有所不同: 当读

linux系统编程:线程同步-读写锁(rwlock)

线程同步-读写锁(rwlock) 读写锁 读写锁是互斥量的细化:显然,只有对全局资然进行写入操作时,才需要同步:在对全局资然进行读取操作时,是不需要锁的. 相关函数 pthread_rwlock_t //读写锁类型 pthread_rwlock_init //初始化 pthread_rwlock_destroy //销毁锁 pthread_rwlock_rdlock //获取读锁 pthread_rwlock_wrlock //获取写锁 pthread_rwlock_tryrdlock pthr

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

在第十一篇文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法--读写锁SRWLock来解决这一问题.读写锁在对资源进行保护的同时,还能区分想要读取资源值的线程(读取者线程)和想要更新资源的线程(写入者线程).对于读取者线程,读写锁会允许他们并发的执行.当有写入者线程在占有资源时,读写锁会让其它写入者线程和读取者线程等待.因此用读写锁来解决读者写者问题会使代码非常清晰和简洁. 下面就来看看如何使用读写锁,要注意编译读写锁程序需要V

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

在<秒杀多线程第十一篇读者写者问题>文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法——读写锁SRWLock来解决这一问题.读 写锁在对资源进行保护的同时,还能区分想要读取资源值的线程(读取者线程)和想要更新资源的线程(写入者线程).对于读取者线程,读写锁会允许他们并发的 执行.当有写入者线程在占有资源时,读写锁会让其它写入者线程和读取者线程等待.因此用读写锁来解决读者写者问题会使代码非常清晰和简洁. 下面就来看看如何使用读

UNIX网络编程:读写锁

之前我们整理了互斥锁与条件变量问题它保证了共享资源的安全,但在多线程中我们也会经常对共享数据进行读.写操作.也就是说对某些资源的访问会 存在两种可能的情况,一种是访问必须是排查性的,就是独占的意思,这称作写操作:另一种情况就是访问方式可以是共享的,就是说可以有多个线程同时去访问某个资源,这种就称作读操作.这个问题模型是从对文件的读写操作中引申出来的. 读写锁比起mutex具有更高的适用性,具有更高的并行性,可以有多个线程同时占用读模式的读写锁,但是只能有一个线程占用写模式的读写锁,读写锁的三种状

linux线程同步(3)-读写锁

一.概述                                                    读写锁与互斥量的功能类似,对临界区的共享资源进行保护!互斥量一次只让一个线程进入临界区,读写锁比它有更高的并行性.读写锁有以下特点: 1.如果一个线程用读锁锁定了临界区,那么其他线程也可以用读锁来进入临界区,这样就可以多个线程并行操作.但这个时候,如果再进行写锁加锁就会发生阻塞,写锁请求阻塞后,后面如果继续有读锁来请求,这些后来的读锁都会被阻塞!这样避免了读锁长期占用资源,防止写锁饥饿

读写锁详解

1. 综述 在一些程序中存在读者写者问题,也就是说,对某些资源的访问会存在两种可能的情况,一种是访问必须是排它行的,就是独占的意思,这称作写操作:另一种情况就是访问方式可以是共享的,就是说可以有多个线程同时去访问某个资源,这种就称作读操作.这个问题模型是从对文件的读写操作中引申出来的.    读写锁比起mutex具有更高的适用性,具有更高的并行性,可以有多个线程同时占用读模式的读写锁,但是只能有一个线程占用写模式的读写锁,读写锁的三种状态: (1)当读写锁是写加锁状态时,在这个锁被解锁之前,所有

信号量、互斥锁,读写锁和条件变量的区别

信号量强调的是线程(或进程)间的同步:“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都 在sem_wait的时候,就阻塞在那里).当信号量为单值信号量是,也可以完成一个资源的互斥访问.有名信号量:可以用于不同进程间或多线程间的互斥与同步 创建打开有名信号量 sem_t *sem_open(const char *name, int oflag); sem_t *sem_open(const char *name, int oflag