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

1. 当读写锁是写加锁状态时,在这个锁被解锁之前,全部试图对这个锁加锁的线程都会被堵塞;

2. 当读写锁在读加锁状态时,全部试图以读模式对它进行加锁的线程都能够得到訪问权。可是以写模式对它进行枷锁的线程将堵塞;

3. 当读写锁在读模式锁状态时,假设有另外线程试图以写模式加锁,读写锁一般会堵塞随后的读模式锁请求,这样能够避免读模式锁长期占用。而等待的写模式锁请求长期堵塞;

这样的锁适用对数据结构进行读的次数比写的次数多的情况下。由于能够进行读锁共享。

API接口说明:

1) 初始化和销毁

  1. #include <pthread.h>
  2. int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
  3. int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

成功则返回0, 出错则返回错误编号.

2) 读加锁和写加锁

获取锁的两个函数是堵塞操作

  1. #include <pthread.h>
  2. int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
  3. int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
  4. int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

成功则返回0, 出错则返回错误编号.

3) 非堵塞获得读锁和写锁

非堵塞的获取锁操作, 假设能够获取则返回0, 否则返回错误的EBUSY.

  1. #include <pthread.h>
  2. int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
  3. int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

成功则返回0, 出错则返回错误编号.

实例代码

  1. /*************************************************************
  2. * pthread_rwlock_test2.c:验证读写锁的默认顺序
  3. * 假设在main函数中用pthread_rwlock_wrlock上锁。那么
  4. * 假设全部线程都堵塞在写锁上的时候,优先处理的是被堵塞的写锁
  5. * 然后才处理读出锁
  6. * 假设在main函数中用pthread_rwlock_rdlock上锁。那么
  7. * 假设有读者正在读的时候即使后面到来的写者比另外一些到来的读者更早
  8. * 也是先处理完读者,才转而处理写者,这样会导致写饥饿
  9. *
  10. * 由此(运行结果)能够看出,LINUX平台默认的是读者优先。假设想要以写者优先
  11. * 则须要做一些处理
  12. **************************************************************/
  13. #include <stdio.h>
  14. #include <pthread.h>
  15. #include <stdlib.h>
  16. pthread_rwlock_t rwlock;
  17. void *readers(void *arg)
  18. {
  19. pthread_rwlock_rdlock(&rwlock);
  20. printf("reader %d got the lock\n", (int)arg);
  21. pthread_rwlock_unlock(&rwlock);
  22. //return NULL;
  23. }
  24. void *writers(void *arg)
  25. {
  26. pthread_rwlock_wrlock(&rwlock);
  27. printf("writer %d got the lock\n", (int)arg);
  28. pthread_rwlock_unlock(&rwlock);
  29. //return NULL;
  30. }
  31. int main(int argc, char **argv)
  32. {
  33. int retval, i;
  34. pthread_t writer_id, reader_id;
  35. pthread_attr_t attr;
  36. int nreadercount = 1, nwritercount = 1;
  37. if (argc != 2) {
  38. fprintf(stderr, "usage, <%s threadcount>", argv[0]);
  39. return -1;
  40. }
  41. retval = pthread_rwlock_init(&rwlock, NULL);
  42. if (retval) {
  43. fprintf(stderr, "init lock failed\n");
  44. return retval;
  45. }
  46. pthread_attr_init(&attr);
  47. //pthread_attr_setdetachstate用来设置线程的分离状态
  48. //也就是说一个线程怎么样终止自己,状态设置为PTHREAD_CREATE_DETACHED
  49. //表示以分离状态启动线程
  50. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  51. //分别在main函数中对读出者和写入者加锁。得到的处理结果是不一样的
  52. pthread_rwlock_wrlock(&rwlock);
  53. // pthread_rwlock_rdlock(&rwlock);
  54. for (i = 0; i < atoi(argv[1]); i++) {
  55. if (random() % 2) {
  56. pthread_create(&reader_id, &attr, readers, (void *)nreadercount);
  57. printf("create reader %d\n", nreadercount++);
  58. } else {
  59. pthread_create(&writer_id, &attr, writers, (void *)nwritercount);
  60. printf("create writer %d\n", nwritercount++);
  61. }
  62. }
  63. printf("main unlock\n");
  64. pthread_rwlock_unlock(&rwlock);
  65. sleep(5);//sleep是为了等待另外的线程的运行
  66. return 0;
  67. }

參考:

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. js应用中的小细节-时间戳的转换和input输入框有效数字

    1 input输入框内value值保留有效数字,js自带的方法.toFixed(),但是直接使用会报错,因为不论输入框内输入汉字.字母还是数字,类型都是string.解决的办法是将其转换为number ...

  2. Image Processing for Very Large Images

    The key idea here is the partial image descriptor VIPS(VASARI Image Processing System) 是近几年逐渐兴起的针对大图 ...

  3. ASP.NET-后台cookie与前台JQUERY解析cookie

    在controller中给cookie赋值 HttpCookie cookie =newHttpCookie("pageInfo"); cookie["page_inde ...

  4. Tokyo Tyrant(TTServer)系列(二)-启动參数和配置

    启动參数介绍         ttserver命令能够启动一个数据库实例.由于数据库已经实现了Tokyo Cabinet的抽象API,所以能够在启动的时候指定数据库的配置类型. 支持的数据库类型有: ...

  5. Ubuntu: GlusterFS+HBase安装教程

    HBase通常安装在Hadoop HDFS上,但也能够安装在其它实现了Hadoop文件接口的分布式文件系统上.如KFS. glusterfs是一个集群文件系统可扩展到几peta-bytes. 它集合了 ...

  6. 上传文件 nginx 413错误

    nginx : 413 Request Entity Too Large 上传文件过程发生413 Request Entity Too Large错误,翻译为请求实体过大,断定为nginx限制了请求体 ...

  7. 安卓通过OkHttp获取json数据

    使用Http协议访问网络 OkHttp使用 可以很好的获取接口数据!json数据! 支持get和post提交方式!!! 1.引入模块 compile 'com.squareup.okhttp3:okh ...

  8. nyoj--514--1的个数(贪心)

     1的个数 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 给你两个数a和b,你的任务是计算出1在a和b之间出现的次数,比如说,如果a=1024,b=1032,那么a ...

  9. matplotlib 可视化 —— matplotlib.patches

    官方帮助文档 patches - Matplotlib 1.5.1 documentation patches 下主要包含的常用图形类有: Eclipse Circle Wedge 1. plt.gc ...

  10. 1. Git-2.12.0-64-bit .exe下载

    转自:https://blog.csdn.net/u011164906/article/details/59129835 之前一直用SVN最近接触git,Git-2.12.0-64-bit .exe文 ...