linux线程同步(3)-读写锁
一.概述
读写锁与互斥量的功能类似,对临界区的共享资源进行保护!互斥量一次只让一个线程进入临界区,读写锁比它有更高的并行性。读写锁有以下特点:
1.如果一个线程用读锁锁定了临界区,那么其他线程也可以用读锁来进入临界区,这样就可以多个线程并行操作。但这个时候,如果再进行写锁加锁就会发生阻塞,写锁请求阻塞后,后面如果继续有读锁来请求,这些后来的读锁都会被阻塞!这样避免了读锁长期占用资源,防止写锁饥饿!
2.如果一个线程用写锁锁住了临界区,那么其他线程不管是读锁还是写锁都会发生阻塞!
二.函数接口
1.创建读写锁
1.1:宏常量初始化
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
1.2:函数初始化
#include <pthread.h> int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
rwlock:读写锁的pthread_rwlock_t结构指针
attr:读写锁的属性结构指针。不需要别的属性默认为NULL。
2.读写锁加锁与解锁
#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);
rwlock:创建的读写锁指针
3.其他类型的加锁
#include <pthread.h> #include <time.h> int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout); int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);
try类函数加锁:如果获取不到锁,会立即返回错误EBUSY!
timed类函数加锁:如果规定的时间内获取不到锁,会返回ETIMEDOUT错误!
4.销毁读写锁
#include <pthread.h> int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
三.简单的例子
创建4个线程,2个线程读锁,2个线程写锁,观察4个线程进入临界区的顺序:
/**
* @file pthread_rwlock.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
/* 初始化读写锁 */
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
/* 全局资源 */
;
void err_exit(const char *err_msg)
{
printf("error:%s\n", err_msg);
exit();
}
/* 读锁线程函数 */
void *thread_read_lock(void *arg)
{
char *pthr_name = (char *)arg;
)
{
/* 读加锁 */
pthread_rwlock_rdlock(&rwlock);
printf("线程%s进入临界区,global_num = %d\n", pthr_name, global_num);
sleep();
printf("线程%s离开临界区...\n", pthr_name);
/* 读解锁 */
pthread_rwlock_unlock(&rwlock);
sleep();
}
return NULL;
}
/* 写锁线程函数 */
void *thread_write_lock(void *arg)
{
char *pthr_name = (char *)arg;
)
{
/* 写加锁 */
pthread_rwlock_wrlock(&rwlock);
/* 写操作 */
global_num++;
printf("线程%s进入临界区,global_num = %d\n", pthr_name, global_num);
sleep();
printf("线程%s离开临界区...\n", pthr_name);
/* 写解锁 */
pthread_rwlock_unlock(&rwlock);
sleep();
}
return NULL;
}
int main(void)
{
pthread_t tid_read_1, tid_read_2, tid_write_1, tid_write_2;
/* 创建4个线程,2个读,2个写 */
)
err_exit("create tid_read_1");
)
err_exit("create tid_read_2");
)
err_exit("create tid_write_1");
)
err_exit("create tid_write_2");
/* 随便等待一个线程,防止main结束 */
)
err_exit("pthread_join()");
;
}
2个线程函数的临界区里面都sleep(1),测试给足够的时间看其他线程能不能进来。64行,写锁函数里面,sleep(2),因为写锁请求会阻塞后面的读锁,2个写锁一起请求会让读锁饥饿,所以比39行的sleep(1)多一秒!
编译运行:

可以看到,读锁可以一起进入临界区,而写锁在临界区里面等1秒都不会有其他线程能进来!!!
linux线程同步(3)-读写锁的更多相关文章
- Linux线程同步之读写锁(rwlock)
读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 和 ...
- UNIX环境高级编程——线程同步之读写锁以及属性
读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 互 ...
- 线程同步——用户模式下线程同步——Slim读写锁实现线程同步
//Slim读/写锁实现线程同步 SRWlock 的目的和关键段相同:对同一资源进行保护,不让其它线程访问. 但是,与关键段不同的是,SRWlock允许我们区分哪些想要读取资源的线程(读取者线程) 和 ...
- linux c编程:读写锁
什么是读写锁读写锁其实还是一种锁,是给一段临界区代码加锁,但是此加锁是在进行写操作的时候才会互斥,而在进行读的时候是可以共享的进行访问临界区的 为什么需要读写锁有时候,在多线程中,有一些公共数据修改的 ...
- linux线程间同步(1)读写锁
读写锁比mutex有更高的适用性,能够多个线程同一时候占用读模式的读写锁.可是仅仅能一个线程占用写模式的读写锁. 1. 当读写锁是写加锁状态时,在这个锁被解锁之前,全部试图对这个锁加锁的线程都会被堵塞 ...
- 嵌入式 Linux线程同步读写锁rwlock示例
读写锁比mutex有更高的适用性,可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁.1. 当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞:2. ...
- linux kernel RCU 以及读写锁
信号量有一个很明显的缺点,没有区分临界区的读写属性,读写锁允许多个线程进程并发的访问临界区,但是写访问只限于一个线程,在多处理器系统中允许多个读者访问共享资源,但是写者有排他性,读写锁的特性如下:允许 ...
- 线程高级篇-读写锁ReentrantReadWriteLock
转载原文:http://blog.csdn.net/john8169/article/details/53228016 读写锁: 分为读锁和写锁,多个读锁不互斥,读锁和写锁互斥,这是有JVM自己控制的 ...
- 线程中的读写锁ReadWriteLock
Lock锁还有两个非常强大的类 ReadWriteLock接口实现类ReentrantReadWriteLock(非常重要的锁) 想实现 读取的时候允许多线程并发访问,写入的时候不允许. 这种效果.. ...
随机推荐
- CentOS系统Kernel panic - not syncing: Attempted to kill init
结果启动虚拟机出现如下问题: Kernel panic - not syncing: Attempted to kill init 解决方法: 系统启动的时候,按下'e'键进入grub编辑界面 ...
- jquery多次上传同一张图片
$().reset(); wrap():$('p').wrap('div');===><div><p></p></div>; .closest() ...
- io.js - 兼容 NPM 平台的 Node.js 新分支
io.js(JavaScript I/O)是兼容 NPM 平台的 Node.js 新分支,由 Node.js 的核心开发者在 Node.js 的基础上,引入更多的 ES6 特性,它的目的是提供更快的和 ...
- asp.net保存网上图片到服务器
本文讲述的是根据一个图片的url地址,保存图片到asp.net服务器端的实现方法. 可以先了解这篇文章http://keleyi.com/a/bjac/0899dpgi.htm,以更好的理解本文. 首 ...
- 《Javascript高级程序设计》:创建对象
工厂模式 function createPerson(name,age, job){ var o = new Object(); o.name = name; o.age = age; o.job = ...
- iOS 使用AFNetworking遇到错误 Request failed: unacceptable content-type: text/html
错误日志: Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacc ...
- silverlight如何通过单独部署的WCF站点访问sharepoint2013的图片库
最近有项目silverlight通过单独部署的WCF站点访问sharepoint2013的图片库,需要做个笑脸墙效果如下: 结果开发完毕后无法在SP站点显示出来.使用VS自带的WCF工具进行测试.如下 ...
- C# 操作PPt,去掉文本框的边框
using System; using System.Collections.Generic; using System.Linq; using System.Text; using OFFICECO ...
- Sharepoint学习笔记—习题系列--70-576习题解析 -(Q13-Q15)
Question 13 You are designing a SharePoint 2010 site. You need to design the site to meet all the fo ...
- iOS开发之──传感器使用 (转载)
在实际的应用开发中,会用到传感器,下面首先介绍一下iphone4的传感器,然后对一些传感器的开发的API作一简单介绍. AD:WOT2015 互联网运维与开发者大会 热销抢票 在实际的应用开发中,会用 ...