一.概述                                                   

读写锁与互斥量的功能类似,对临界区的共享资源进行保护!互斥量一次只让一个线程进入临界区,读写锁比它有更高的并行性。读写锁有以下特点:

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

  1. Linux线程同步之读写锁(rwlock)

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

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

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

  3. 线程同步——用户模式下线程同步——Slim读写锁实现线程同步

    //Slim读/写锁实现线程同步 SRWlock 的目的和关键段相同:对同一资源进行保护,不让其它线程访问. 但是,与关键段不同的是,SRWlock允许我们区分哪些想要读取资源的线程(读取者线程) 和 ...

  4. linux c编程:读写锁

    什么是读写锁读写锁其实还是一种锁,是给一段临界区代码加锁,但是此加锁是在进行写操作的时候才会互斥,而在进行读的时候是可以共享的进行访问临界区的 为什么需要读写锁有时候,在多线程中,有一些公共数据修改的 ...

  5. linux线程间同步(1)读写锁

    读写锁比mutex有更高的适用性,能够多个线程同一时候占用读模式的读写锁.可是仅仅能一个线程占用写模式的读写锁. 1. 当读写锁是写加锁状态时,在这个锁被解锁之前,全部试图对这个锁加锁的线程都会被堵塞 ...

  6. 嵌入式 Linux线程同步读写锁rwlock示例

    读写锁比mutex有更高的适用性,可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁.1. 当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞:2. ...

  7. linux kernel RCU 以及读写锁

    信号量有一个很明显的缺点,没有区分临界区的读写属性,读写锁允许多个线程进程并发的访问临界区,但是写访问只限于一个线程,在多处理器系统中允许多个读者访问共享资源,但是写者有排他性,读写锁的特性如下:允许 ...

  8. 线程高级篇-读写锁ReentrantReadWriteLock

    转载原文:http://blog.csdn.net/john8169/article/details/53228016 读写锁: 分为读锁和写锁,多个读锁不互斥,读锁和写锁互斥,这是有JVM自己控制的 ...

  9. 线程中的读写锁ReadWriteLock

    Lock锁还有两个非常强大的类 ReadWriteLock接口实现类ReentrantReadWriteLock(非常重要的锁) 想实现 读取的时候允许多线程并发访问,写入的时候不允许. 这种效果.. ...

随机推荐

  1. selenium启动firefox时加载扩展

    有些时候,我们测试需要用到插件或者已经导入的证书(比如金融和安全加密行业),而selenium启动firefox时会打开一个新的,不含有任何插件和个人证书的firefox(等同于全新安装后第一次打开的 ...

  2. B树详解

    B树 具体讲解之前,有一点,再次强调下:B-树,即为B树.因为B树的原英文名称为B-tree,而国内很多人喜欢把B-tree译作B-树,其实,这是个非常不好的直译,很容易让人产生误解.如人们可能会以为 ...

  3. 【自然框架】终于把源码弄到git上了。

    好久没写博客了,发现又从左面的排名里掉出去了. 说来惭愧,一直说是开源,但是源码一直没能放到git里面.原因是,不会用. 最近终于把git弄明白了.把源码都放进去了. 刚兴趣的话可以来看看. http ...

  4. jQuery演示10种不同的切换图片列表动画效果

    经常用到的图片插件演示jQuery十种不同的切换图片列表动画效果 在线演示 下载地址 实例代码 <!DOCTYPE html> <html lang="en" c ...

  5. jQuery Sidebar 侧边栏

    在线实例 左边栏 右边栏 使用方法     <div class="txt">             <p class="btn"> ...

  6. 【特别推荐】几款极好的 JavaScript 下拉列表插件

    表单元素让人爱恨交加.作为网页最重要的组成部分,表单几乎无处不在,从简单的邮件订阅.登陆注册到复杂的需要多页填写的信息提交功能,表单都让开发者花费了大量的时间和精力去处理,以期实现好用又漂亮的表单功能 ...

  7. .net MVC 连接数据本地数据库三种方法

    <appSettings> <add key="webpages:Version" value="2.0.0.0" /> <add ...

  8. Autodesk 招人了,开发顾问,感兴趣的或者有推荐的人扔简历过来啊

    Autodesk ADN招人了,在上海,开发顾问, JD如下. 如果你感兴趣或者有人推荐,扔简历过来啊, daniel.du@autodesk.com,赶早不赶晚啊.   Job Title: Dev ...

  9. 国内第一篇详细讲解hadoop2的automatic HA+Federation+Yarn配置的教程

    前言 hadoop是分布式系统,运行在linux之上,配置起来相对复杂.对于hadoop1,很多同学就因为不能搭建正确的运行环境,导致学习兴趣锐减.不过,我有免费的学习视频下载,请点击这里. hado ...

  10. 关于SharPoint2013一点细节的深究

    在进行SharePoint2013的开发过程中我发现在开启了某些功能,或者说是创建了个人站点之后有很多地方变了比如下面这个地方:     当然相应的URL地址也发生改变.也许很明确的我就打开了Welc ...