读写锁比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)读写锁的更多相关文章

  1. linux线程间同步方式汇总

    抽空做了下linux所有线程间同步方式的汇总(原生的),包含以下几个: 1, mutex 2, condition variable 3, reader-writer lock 4, spin loc ...

  2. linux线程间同步方式总结梳理

    线程间一般无需特别的手段进行通信,由于线程间能够共享数据结构,也就是一个全局变量能够被两个线程同时使用.只是要注意的是线程间须要做好同步! 使用多线程的理由: 1. 一个是和进程相比,它是一种非常&q ...

  3. Linux线程间同步的几种方式

    信号量 信号量强调的是线程(或进程)间的同步:"信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在sem_wait的时候,就阻塞 ...

  4. 四十、Linux 线程——互斥锁和读写锁

    40.1 互斥锁 40.1.1 介绍 互斥锁(mutex)是一种简单的加锁的方法来控制对共享资源的访问. 在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行访问. 若其他线程 ...

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

    一.概述                                                    读写锁与互斥量的功能类似,对临界区的共享资源进行保护!互斥量一次只让一个线程进入临界区, ...

  6. UNIX环境高级编程——线程同步之读写锁以及属性

    读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 互 ...

  7. Linux系统编程(29)——线程间同步(续篇)

    线程间的同步还有这样一种情况:线程A需要等某个条件成立才能继续往下执行,现在这个条件不成立,线程A就阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行.在pthread库中通过条件变 ...

  8. C#线程间同步无法关闭

    用C#做了个线程间同步的小程序,但每次关闭窗口后进程仍然在,是什么原因? 解决方法: 要加一句 线程.IsBackground = true; 否则退出的只是窗体 上面的方法没看懂... MSDN上说 ...

  9. Linux多线程实践(6) --Posix读写锁解决读者写者问题

    Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *rest ...

随机推荐

  1. vue解决跨域问题

    vue解决跨域问题 vue跨域解决方法和小总结 vue项目中,前端与后台进行数据请求或者提交的时候,如果后台没有设置跨域,前端本地调试代码的时候就会报“No 'Access-Control-Allow ...

  2. tp 在Nginx上各种404

    对于ThinkPHP的URL访问路劲如:http://域名/index.php/Index/BlogTest/read,原先的Nginx的是不支持的pathinfo路劲的,导致你在thinkPHP5上 ...

  3. Ubuntu 常用快捷键

    本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50285313 1 桌面 快捷键 作用 ...

  4. spring boot学习(转)

    玩转Spring Boot 前言         首先在这里对Spring Boot做个简单的介绍,对Spring Boot也关注了挺久了,Spring Boot是由Pivotal团队提供的全新框架, ...

  5. HDU 4307 Contest 1

    http://www.cnblogs.com/staginner/archive/2012/08/13/2636826.html 自己看过后两周吧,重新写了一遍.很受启发的.对于0.1,可以使用最小割 ...

  6. HDU 4390 Number Sequence (容斥原理+组合计数)

    HDU 4390 题意: 大概就是这样.不翻译了: Given a number sequence b1,b2-bn. Please count how many number sequences a ...

  7. IntelliJ IDEA 初始化项目时No Java SDK Found

    IntelliJ IDEA 初始化项目时No Java SDK Found 自己在Project SDK后面的New按钮进行JDK的添加:

  8. [Python + Unit Testing] Write Your First Python Unit Test with pytest

    In this lesson you will create a new project with a virtual environment and write your first unit te ...

  9. Struts2学习(四)利用ajax异步上传

    上一篇说到怎样在struts2中进行上传下载.我们使用了struts的标签通过表单提交的方式,但大家知道表单提交会造成页面总体的刷新,这样的方式很不友好,那我们今天就来说说怎样结合ajax方式进行异步 ...

  10. 疯狂Java学习笔记(70)-----------挚爱Java

    与大家分享! 挚爱Java 10个使用Java最广泛的现实领域 写好Java代码的30条经验总结 Java字符串的substring真的会引起内存泄露么? Java内存的原型及工作原理深度剖析 Jav ...