读写锁机制

  在以前的一篇博文Linux多线程编程初探中,只提到了用于线程同步的互斥锁、条件变量,而没有提及读写锁(read-write lock)。

  本文主要整理自以下文章:

  读写锁(read-write lock)机制-----多线程同步问题的解决

  请用普通的互斥锁编程实现一个读写锁

读写锁

  读写锁比mutex有更高的适用性,可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁。

  1)当读写锁是写加锁状态时, 在这个锁被解锁之前, 所有试图对这个锁加锁的线程都会被阻塞.

  2)当读写锁在读加锁状态时, 所有试图以读模式对它进行加锁的线程都可以得到访问权,但是以写模式对它进行枷锁的线程将阻塞;

  3)当读写锁在读模式锁状态时, 如果有另外线程试图以写模式加锁读写锁通常会阻塞随后的读模式锁请求, 这样可以避免读模式锁长期占用, 而等待的写模式锁请求长期阻塞;

  这种锁适用对数据结构进行读的次数比写的次数多的情况。

读写锁API

初始化和销毁

  对于读写锁变量的初始化可以有两种方式,一种是通过给一个静态分配的读写锁赋予常值PTHREAD_RWLOCK_INITIALIZER来初始化它,另一种方法就是通过调用pthread_rwlock_init()来动态的初始化。而当某个线程不再需要读写锁的时候,可以通过调用pthread_rwlock_destroy来销毁该锁。函数原型如下:

#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
// 成功则返回0, 出错则返回错误编号.

  在释放某个读写锁占用的内存之前,要先通过pthread_rwlock_destroy对读写锁进行清理,释放由pthread_rwlock_init所分配的资源。在初始化某个读写锁的时候,如果属性指针attr是个空指针的话,表示默认的属性;如果想要使用非默认属性,则要使用到下面的两个函数:

#include
int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
int pthread_rwlockattr_destroy(pthread_rwlockatttr_t *attr);
// 成功返回0,出错则返回错误码。

  这里还需要说明的是,当初始化读写锁完毕以后呢,该锁就处于一个非锁定状态。数据类型为pthread_rwlockattr_t的某个属性对象一旦初始化了,就可以通过不同的函数调用来启用或者是禁用某个特定的属性。

读加锁和写加锁

  读写锁的数据类型是pthread_rwlock_t,如果这个数据类型中的某个变量是静态分配的,那么可以通过给它赋予常值PTHREAD_RWLOCK_INITIALIZAR来初始化它。pthread_rwlock_rdlock()用来获取读出锁,如果相应的读出锁已经被某个写入者占有,那么就阻塞调用线程。pthread_rwlock_wrlock()用来获取一个写入锁,如果相应的写入锁已经被其它写入者或者一个或多个读出者占有,那么就阻塞该调用线程;pthread_rwlock_unlock()用来释放一个读出或者写入锁。函数原型如下:

#include <pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
// 成功则返回0, 出错则返回错误编号.

  要注意的是其中获取锁的两个函数的操作都是阻塞操作,也就是说获取不到锁的话,那么调用线程不是立即返回,而是阻塞执行。有写情况下,这种阻塞式的获取所得方式可能不是很适用,所以,接下来引入两个采用非阻塞方式获取读写锁的函数pthread_rwlock_tryrdlock()和pthread_rwlock_trywrlock(),非阻塞方式下获取锁的时候,如果不能马上获取到,就会立即返回一个EBUSY错误,而不是把调用线程投入到睡眠等待。函数原型如下:

#include <pthread.h>
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
// 成功则返回0, 出错则返回错误编号.

用互斥锁实现读写锁

  伪代码如下:

 1 count_mutex = mutex_init();
 2 write_mutex = mutex_init();
 3 read_count = 0;
 4
 5 void read_lock{
 6     lock(count_mutex);
 7     read_count++;
 8     if (read_count == 1) {
 9         lock(write_mutex);
10     }
11     unlock(count_mutex);
12 }
13
14 void read_unlock{
15     lock(count_mutex);
16     read_count--;
17     if (read_count == 0) {
18         unlock(write_mutex);
19     }
20     unlock(count_mutex);
21 }
22
23 void write_lock{
24     lock(write_mutex);
25 }
26
27 void write_unlock{
28     unlock(write_mutex);
29 }

  

时间: 2024-10-24 00:19:54

读写锁机制的相关文章

多线程读写锁机制

1 #include <stdio.h> 2 #include <pthread.h> 3 #include <stdio.h> 4 #include <errno.h> 5 #include <stdlib.h> 6 static pthread_rwlock_t rwlock; 7 #define WORK_SIZE 1024 8 char work_area[WORK_SIZE]; 9 int time_to_exit=0; 10 11 v

Linux程序设计学习笔记----多线程编程线程同步机制之互斥量(锁)与读写锁

互斥锁通信机制 基本原理 互斥锁以排他方式防止共享数据被并发访问,互斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个互斥锁逻辑上绑定之后,对该资源的访问操作如下: (1)在访问该资源之前需要首先申请互斥锁,如果锁处于开状态,则申请得到锁并立即上锁(关),防止其他进程访问资源,如果锁处于关,则默认阻塞等待. (2)只有锁定该互斥锁的进程才能释放该互斥锁. 互斥量类型声明为pthread_mutex_t数据类型,在<bits/pthreadtypes.h>中有具体的定义. 互斥量

读写锁(read-write lock)机制-----多线程同步问题的解决

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

读写锁详解

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

c++ 读写锁

#ifndef THREAD_UTIL_H #define THREAD_UTIL_H #include <pthread.h> namespace spider { class AutoLock { pthread_mutex_t * _lock; public: AutoLock(pthread_mutex_t * lock) { _lock = lock; pthread_mutex_lock(_lock); } ~AutoLock() { pthread_mutex_unlock(_l

【C/C++多线程编程之九】pthread读写锁

多线程编程之读写锁 Pthread是 POSIX threads 的简称,是POSIX的线程标准.  pthread读写锁把对共享资源的访问者分为读者和写者,读者只对共享资源进行读访问,写者只对共享资源进行写操作.在互斥机制,读者和写者都需要独立独占互斥量以独占共享资源,在读写锁机制下,允许同时有多个读者读访问共享资源,只有写者才需要独占资源.相比互斥机制,读写机制由于允许多个读者同时读访问共享资源,进一步提高了多线程的并发度.                   1.读写锁机制:      

动手实现读写锁

排他锁的弊端 在多个线程之间共享数据,普遍做法是加锁读写,也就是同一个时刻只有一个线程能够读或者写,以保证数据一致性,即线程安全.例如下面的代码是普遍的做法 1 void Read() 2 { 3 Lock(mutex); 4 5 // 读取数据 6 7 UnLock(mutex); 8 } 9 10 void Write() 11 { 12 Lock(mutex); 13 14 // 写入数据 15 16 UnLock(mutex); 17 } 读写锁的设计 这样的锁是具有排他性的,会在一定程

读写锁、自旋锁

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

xfchgfwwwbb0002com可重入读写锁 ReentrantReadW19908836661

ava 中的并发锁大致分为隐式锁和显式锁两种.隐式锁就是我们最常使用的 synchronized 关键字,显式锁主要包含两个接口:Lock 和 ReadWriteLock,主要实现类分别为 ReentrantLock 和 ReentrantReadWriteLock,这两个类都是基于 AQS(AbstractQueuedSynchronizer) 实现的.还有的地方将 CAS 也称为一种锁,在包括 AQS 在内的很多并发相关类中,CAS 都扮演了很重要的角色.我们只需要弄清楚 synchroni