linux线程间同步(1)读写锁
读写锁比mutex有更高的适用性,能够多个线程同一时候占用读模式的读写锁。可是仅仅能一个线程占用写模式的读写锁。
1. 当读写锁是写加锁状态时,在这个锁被解锁之前,全部试图对这个锁加锁的线程都会被堵塞;
2. 当读写锁在读加锁状态时,全部试图以读模式对它进行加锁的线程都能够得到訪问权。可是以写模式对它进行枷锁的线程将堵塞;
3. 当读写锁在读模式锁状态时,假设有另外线程试图以写模式加锁,读写锁一般会堵塞随后的读模式锁请求,这样能够避免读模式锁长期占用。而等待的写模式锁请求长期堵塞;
这样的锁适用对数据结构进行读的次数比写的次数多的情况下。由于能够进行读锁共享。
API接口说明:
1) 初始化和销毁
#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, 出错则返回错误编号.
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);
成功则返回0, 出错则返回错误编号.
3) 非堵塞获得读锁和写锁
非堵塞的获取锁操作, 假设能够获取则返回0, 否则返回错误的EBUSY.
#include <pthread.h>
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
成功则返回0, 出错则返回错误编号.
实例代码
/*************************************************************
* pthread_rwlock_test2.c:验证读写锁的默认顺序
* 假设在main函数中用pthread_rwlock_wrlock上锁。那么
* 假设全部线程都堵塞在写锁上的时候,优先处理的是被堵塞的写锁
* 然后才处理读出锁
* 假设在main函数中用pthread_rwlock_rdlock上锁。那么
* 假设有读者正在读的时候即使后面到来的写者比另外一些到来的读者更早
* 也是先处理完读者,才转而处理写者,这样会导致写饥饿
*
* 由此(运行结果)能够看出,LINUX平台默认的是读者优先。假设想要以写者优先
* 则须要做一些处理
**************************************************************/
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
pthread_rwlock_t rwlock;
void *readers(void *arg)
{
pthread_rwlock_rdlock(&rwlock);
printf("reader %d got the lock\n", (int)arg);
pthread_rwlock_unlock(&rwlock);
//return NULL;
}
void *writers(void *arg)
{
pthread_rwlock_wrlock(&rwlock);
printf("writer %d got the lock\n", (int)arg);
pthread_rwlock_unlock(&rwlock);
//return NULL;
}
int main(int argc, char **argv)
{
int retval, i;
pthread_t writer_id, reader_id;
pthread_attr_t attr;
int nreadercount = 1, nwritercount = 1;
if (argc != 2) {
fprintf(stderr, "usage, <%s threadcount>", argv[0]);
return -1;
}
retval = pthread_rwlock_init(&rwlock, NULL);
if (retval) {
fprintf(stderr, "init lock failed\n");
return retval;
}
pthread_attr_init(&attr);
//pthread_attr_setdetachstate用来设置线程的分离状态
//也就是说一个线程怎么样终止自己,状态设置为PTHREAD_CREATE_DETACHED
//表示以分离状态启动线程
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
//分别在main函数中对读出者和写入者加锁。得到的处理结果是不一样的
pthread_rwlock_wrlock(&rwlock);
// pthread_rwlock_rdlock(&rwlock);
for (i = 0; i < atoi(argv[1]); i++) {
if (random() % 2) {
pthread_create(&reader_id, &attr, readers, (void *)nreadercount);
printf("create reader %d\n", nreadercount++);
} else {
pthread_create(&writer_id, &attr, writers, (void *)nwritercount);
printf("create writer %d\n", nwritercount++);
}
}
printf("main unlock\n");
pthread_rwlock_unlock(&rwlock);
sleep(5);//sleep是为了等待另外的线程的运行
return 0;
}
參考:
linux线程间同步(1)读写锁的更多相关文章
- linux线程间同步方式汇总
抽空做了下linux所有线程间同步方式的汇总(原生的),包含以下几个: 1, mutex 2, condition variable 3, reader-writer lock 4, spin loc ...
- linux线程间同步方式总结梳理
线程间一般无需特别的手段进行通信,由于线程间能够共享数据结构,也就是一个全局变量能够被两个线程同时使用.只是要注意的是线程间须要做好同步! 使用多线程的理由: 1. 一个是和进程相比,它是一种非常&q ...
- Linux线程间同步的几种方式
信号量 信号量强调的是线程(或进程)间的同步:"信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在sem_wait的时候,就阻塞 ...
- 四十、Linux 线程——互斥锁和读写锁
40.1 互斥锁 40.1.1 介绍 互斥锁(mutex)是一种简单的加锁的方法来控制对共享资源的访问. 在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行访问. 若其他线程 ...
- linux线程同步(3)-读写锁
一.概述 读写锁与互斥量的功能类似,对临界区的共享资源进行保护!互斥量一次只让一个线程进入临界区, ...
- UNIX环境高级编程——线程同步之读写锁以及属性
读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 互 ...
- Linux系统编程(29)——线程间同步(续篇)
线程间的同步还有这样一种情况:线程A需要等某个条件成立才能继续往下执行,现在这个条件不成立,线程A就阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行.在pthread库中通过条件变 ...
- C#线程间同步无法关闭
用C#做了个线程间同步的小程序,但每次关闭窗口后进程仍然在,是什么原因? 解决方法: 要加一句 线程.IsBackground = true; 否则退出的只是窗体 上面的方法没看懂... MSDN上说 ...
- Linux多线程实践(6) --Posix读写锁解决读者写者问题
Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *rest ...
随机推荐
- java深克隆与浅克隆
2015.9.19 6:45 星期五 1
- angular-HTTP
AngularJS $http 是一个用于读取web服务器上数据的服务. $http.get(url) 是用于读取服务器数据的函数. <div ng-app="myApp" ...
- window8.1 CenterOS 双系统
window8.1 CenterOS 双系统 学习了: http://blog.csdn.net/ac_hell/article/details/53436890 https://jingyan.ba ...
- NYOJ 915 +-字符串【贪心】
+-字符串 时间限制:1000 ms | 内存限制:65535 KB 难度:1 描写叙述 Shiva得到了两个仅仅有加号和减号的字符串,字串长度同样.Shiva一次能够把一个加号和它相邻的减号交换 ...
- cloudstack给已有zone加入物理网络
默认情况下,假设zone建立完后.cloudstack是不提供加入物理网络接口的. 基础架构- 域 - 物理网络 以下仅仅有我们创建zone的时候加入的物理网络 假设想在这个基础上加入一个物理网络是没 ...
- Activity嵌套多个Fragment实现横竖屏切换
一.上图 二.需求 最近项目遇到个横竖屏切换的问题.较为复杂.在此记之. 1.Activity中竖屏嵌套3个Fragment,本文简称竖屏FP1,FP2,FP3. 2.当中竖屏FP1与FP2能够切换为 ...
- 智课雅思词汇---十二、vent是什么意思
智课雅思词汇---十二.vent是什么意思 一.总结 一句话总结:词根:ven, vent = come, 表示“来” 词根:vent = wind 风 1.tact是什么意思? 词根:-tact-, ...
- ThinkPHP5.0框架开发--第9章 TP5.0视图和模板
ThinkPHP5.0框架开发--第9章 TP5.0视图和模板 第9章 TP5.0视图和模板 ===================================================== ...
- 集群版本升级——rolling upgrade在ES 单节点从 restart 到加入集群,大概要 100s 左右的时间。也就是说,这 100s 内,该节点上的所有分片都是 unassigned 状态
集群版本升级 Elasticsearch 作为一个新兴项目,版本更新非常快.而且每次版本更新都或多或少带有一些重要的性能优化.稳定性提升等特性.可以说,ES 集群的版本升级,是目前 ES 运维必然要做 ...
- zzuoj--1001--汽水瓶(简单数学)
1001: 汽水瓶 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 194 Solved: 77 [Submit][Status][Web Board ...