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

一. 读写锁

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

有读写锁的存在当然就会有读者和写者,也就是多个线程,但是它们之间的相互关系和mutex锁中有所不同:

  1. 当读写锁处于写加锁模式的时候,别的写者或读者就会被阻塞并不能获得锁资源来访问临界资源;
  2. 当读写锁处于读加锁模式的时候,别的读者也可以得到对临界资源的访问权限来读取数据,只是写者请求加锁的线程会被阻塞不能进行加锁;
  3. 当读写锁处于读加锁模式时,如果有写者请求读写锁要进行写加锁,读写锁通常会阻塞随后请求读加锁的线程,避免读写锁一直被读者占用而无法往缓冲区中写入数据;

-------------------------------------------------------------------------------------------

二. 读写锁函数

  1. 读写锁的创建及销毁

函数参数中,

rwlock是类型为pthread_rwlock_t读写锁类型的指针,指向读写锁类型的变量;

attr是表示读写锁的属性,设置为NULL表示使用系统默认属性;

2. 读写锁的加锁及解锁

rwlock是指向读写锁的指针;

pthread_rwlock_wrlock函数是为读者加上读锁模式;

pthread_rwlock_rdlock函数是为写者加上写锁模式;

函数中加入了try表示线程调用该函数的非阻塞模式;

函数成功返回0,失败返回错误码;

-------------------------------------------------------------------------------------------

栗子时间:

上面的栗子中创建了两个读者线程和两个写者线程,读者线程函数加读取锁,写者线程函数加写入锁,运行程序观察结果:

每一次运行程序的结果并不是一样的,这是因为读写锁是有优先级的,在上面的栗子中写者的优先级比较高,第一种结果中,是因为两个写者线程优先获得了读写锁,向buf缓冲区写数据,因此两个读者读到相同的数据,每次读取结果差2;第二种结果中,仍然是写者的优先级高,因为每次都是写者写入数据之后读者才去读取数据,一个线程并没有读到重复的数据,只是当一个写者线程写入数据之后,一个读者线程就获得了读写锁读出了数据,二者交互进行;

-------------------------------------------------------------------------------------------

读写锁是一种自旋锁,和互斥锁不同的是,互斥锁是当锁资源不可用时,申请锁资源的线程就会挂起等待,直到有锁资源可用了才被唤醒;而读写锁是当锁资源被占用的时候并不会挂起等待,而是一直自旋反复请求锁资源,直到锁资源被释放获得为止;

虽然锁类型不同,但是可以用互斥锁和条件变量来模拟读写锁:

上面栗子将读写锁用互斥量和条件变量模拟:

首先,因为写者和写者之间是互斥的关系,因此一定要加上互斥锁;而读者和读者之间并不需要互斥关系,读写锁的高效就是多个读者可以在同一时间段从缓冲区中取出数据,因此读者线程函数中并不需要加入互斥量;那么,要想维持读者和写者之间的互斥关系,就可以加入条件变量,当读者的条件不满足时,也就是写者在向缓冲区中写入数据的时候,读者就需要挂起等待,为了使读者在读取数据的时候写者不往缓冲区写数据,可以让写者sleep上1秒,也就是保证读者再一次进入wait等待的时候写者才获得互斥锁进行缓冲区的操作,当写者写完数据的时候,需要调用pthread_cond_broadcast函数来将所有等待的线程唤醒,也就是读写锁中一个读者获得锁资源别的读者也可有权限访问;

运行程序:

-------------------------------------------------------------------------------------------

总结:

互斥锁可以用于当一个线程需要占用锁的时间比较长时,另外的线程就需要挂起等待,如果使用自旋锁就会一直停留一直自旋请求锁资源;而如果一个线程占用锁的时间并不长,就可以用读写锁这种自旋锁,因为会节省系统不断地挂起唤醒一个进程所耗费的时间,因此,锁的使用可因不同的使用需求综合而定。

《完》

时间: 2024-10-13 02:20:56

读写锁————用互斥量和条件变量模拟的相关文章

浅析线程间通信一:互斥量和条件变量

线程同步的目的简单来讲就是保证数据的一致性.在Linux中,常用的线程同步方法有互斥量( mutex ).读写锁和条件变量,合理使用这三种方法可以保证数据的一致性,但值得的注意的是,在设计应用程序时,所有的线程都必须遵守相同的数据访问规则为前提,才能保证这些同步方法有效,如果允许某个线程在没有得到访问权限(比如锁)的情况下访问共享资源,那么其他线程在使用共享资源前都获得了锁,也会出现数据不一致的问题.另外还有自旋锁.barrier和信号量线程同步方法.本文将讨论互斥量和条件变量的使用,并给出了相

互斥量和条件变量

1.如何利用2个条件变量实现线程同步? 思路:就是来回的利用pthread_cond_signal()函数,当一方被阻塞时,唤醒函数可以唤醒pthread_cond_wait()函数,只不过pthread_cond_wait()这个方法要执行其后的语句,必须遇到下一个阻塞(也就是pthread_cond_wait()方法时),才执行唤醒后的其后语句. 代码如下: #include<stdio.h> #include<unistd.h> #include<stdlib.h>

互斥量和条件变量的区别

互斥量与条件变量的区别 转载自:http://www.360doc.com/content/12/0129/10/1317564_182456205.shtml 前面谈过了线程锁,下面我们在继续研究一下线程锁: 互斥量从本质上来说是一个锁,对互斥量加锁后任何其他试图给它加锁的线程都会被阻塞直至当前线程释放互斥量. 同样在设计时需要规定所有的线程必须遵守相同的数据访问规则,只有这样互斥机制才能正常工作(只要是锁都这样,这是锁工作的本质) 互斥量用pthread_mutex_t 数据类型表示,在使用

生产者-消费者问题:介绍POSIX线程的互斥量和条件变量的使用

全局初始化互斥量和条件变量(不全局也行,但至少要对线程启动函数可见,这样才能使用.) static pthread_cont_t cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; 使用互斥量锁住一块代码方法如下(默认忽略pthread开头的函数的错误检查,即类似 int s = pthread_xxx(...); if (s != 0) { printErrorMsg(

[转]一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程

一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程 希望此文能给初学多线程编程的朋友带来帮助,也希望牛人多多指出错误. 另外感谢以下链接的作者给予,给我的学习带来了很大帮助 http://blog.csdn.net/locape/article/details/6040383 http://www.cnblogs.com/liuweijian/archive/2009/12/30/1635888.html 一.什么是多线程? 当我自己提出这个问题的时候,我还是很老实的拿着操作系

使用互斥量和条件变量实现线程同步控制

管程(monitor)说明 在并发编程中,管程(monitor)是一个同步构件,管程实现了同一时间点,最多只有一个线程可以执行管程的某个子程序.与那些通过修改数据结构实现互斥访问的并发程序设计相比,管程的实现很大程度上简化了程序设计. 管程可以确保一次只有一个进程执行管程中的程序,因此程序员不需要显式地编写同步代码,但是如果需要就某些特定条件上的同步,则需要定义一些条件结构(condition variable)来实现,并且对条件变量的操作仅有wait()和signal(),如下: condit

Linux多线程同步之互斥量和条件变量

1. 什么是互斥量 互斥量从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁.对互斥量进行加锁以后,任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁.如果释放互斥锁时有多个线程阻塞,所以在该互斥锁上的阻塞线程都会变成可进行状态,第一个变成运行状态的线程可以对互斥量加锁,其他线程在次被阻塞,等待下次运行状态. pthread_mutex_t 就是POSIX对于mutex的实现. 函数名 参数 说明 pthread_mutex_init pthre

POSIX 使用互斥量和条件变量实现生产者/消费者问题

boost的mutex,condition_variable非常好用.但是在Linux上,boost实际上做的是对pthread_mutex_t 和pthread_cond_t的一系列的封装.因此通过对原生态的POSIX 的mutex,cond的生成者,消费者的实现,我们可以再次体会boost带给我们的便利. 1. 什么是互斥量 互斥量从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁.对互斥量进行加锁以后,任何其他试图再次对互斥量加锁的线 程将会被阻塞直到当前线

读写锁 与 互斥锁

相交进程之间的关系主要有两种,同步与互斥.所谓互斥,是指散步在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它 们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行.所谓同步,是指散步在不同进程之间的若干程序片断,它们的运行必须严格按照规定的 某种先后次序来运行,这种先后次序依赖于要完成的特定的任务. 显然,同步是一种更为复杂的互斥,而互斥是一种特殊的同步. 也就是说互斥是两个线程之间不可以同时运行,他们会相互排斥,必须等待一个线程运行完毕,另一个