前面介绍的互斥量加锁要么是锁状态,要么就是不加锁状态。而且只有一次只有一个线程可以对其加锁。这样的目的是为了防止变量被不同的线程修改。但是如果有线程只是想读而不会去写的话,这有不会导致变量被修改。但是如果是互斥量加锁,则读写都没有办法。这种场景不能使用互斥量,必须使用读写锁。

读写锁可以有3种状态:

1 读模式下加锁状态

2 写模式下加锁状态

3 不加锁状态

一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁。当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权。但是任何希望以写模式对此锁进行加锁的线程都会阻塞。直到所有的线程释放它们的读锁为止。

读写锁非常适合于对数据结构读的次数大于写的情况。当读写锁在写模式下时,它所保护的数据结构就可以被安全地修改,因为一次只有一个线程可以在写模式下拥有这个锁。

读写锁也叫做共享互斥锁。当读写锁是读模式锁住的,就可以说是以共享模式锁住的。当它是写模式锁住的时候,就可以说成是以互斥模式锁住的。

#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);

读写锁通过调用pthread_rwlock_init进行初始化。在释放读写锁占有的内存之前,需要调用pthread_rwlock_destroy做清理工作。如果pthread_rwlock_init为读写锁分配了资源,pthread_rwlock_destroy将释放这些资源。如果在调用pthread_rwlock_destroy之前就释放了读写锁占用的内存空间。那么分配给这个锁的资源就会丢失。

要在读模式下锁定读写锁,需要调用pthread_rwlock_rdlock,要在写模式下锁定读写锁,需要调用pthread_rwlock_wrlock。不管以何种方式锁住读写锁。都可以调用pthread_rwlock_unlock进行解锁。

#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);

来看一个基本的实现例子:

pthread_rwlock_t rwlock;

int data=1;

void readerA(){

while(1){

pthread_rwlock_rdlock(&rwlock);

printf("A读者读出:%d\n",data);

pthread_rwlock_unlock(&rwlock);

Sleep(1000);

}

}

void writerB(){

while(1){

pthread_rwlock_wrlock(&rwlock);

data++;

printf("B作者写入:%d\n",data);

pthread_rwlock_unlock(&rwlock);

Sleep(1000);

}

}

int main()

{

pthread_t t1;

pthread_t t2;

pthread_rwlock_init(&rwlock,NULL);

pthread_create(&t1,NULL,readerA,NULL);

pthread_create(&t2,NULL,writerB,NULL);

pthread_join(t1,NULL);

pthread_join(t2,NULL);

pthread_rwlock_destroy(&rwlock);

return 0;

}

运行结果如下:可以看到读者A在读取数据的时候,data能够保持原子性。不会被写的操作给抢占而导致数据不一致。

inux c编程:读写锁的更多相关文章

  1. java并发编程-读写锁

    最近项目中需要用到读写锁 读写锁适用于读操作多,写操作少的场景,假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁.在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以 ...

  2. JAVA 并发编程-读写锁之模拟缓存系统(十一)

    在多线程中,为了提高效率有些共享资源同意同一时候进行多个读的操作,但仅仅同意一个写的操作,比方一个文件,仅仅要其内容不变能够让多个线程同一时候读,不必做排他的锁定,排他的锁定仅仅有在写的时候须要,以保 ...

  3. Linux系统编程 —读写锁rwlock

    读写锁是另一种实现线程间同步的方式.与互斥量类似,但读写锁将操作分为读.写两种方式,可以多个线程同时占用读模式的读写锁,这样使得读写锁具有更高的并行性. 读写锁的特性为:写独占,读共享:写锁优先级高. ...

  4. 【C/C++多线程编程之九】pthread读写锁

    多线程编程之读写锁      Pthread是 POSIX threads 的简称,是POSIX的线程标准.         pthread读写锁把对共享资源的訪问者分为读者和写者,读者仅仅对共享资源 ...

  5. 018-并发编程-java.util.concurrent.locks之-ReentrantReadWriteLock可重入读写锁

    一.概述 ReentrantLock是一个排他锁,同一时间只允许一个线程访问,而ReentrantReadWriteLock允许多个读线程同时访问,但不允许写线程和读线程.写线程和写线程同时访问.相对 ...

  6. C# 多线程编程之锁的使用【互斥锁(lock)和读写锁(ReadWriteLock)】

    多线程编程之锁的使用[互斥锁(lock)和读写锁(ReadWriteLock)] http://blog.csdn.net/sqqyq/article/details/18651335 多线程程序写日 ...

  7. java并发编程-StampedLock高性能读写锁

    目录 一.读写锁 二.悲观读锁 三.乐观读 欢迎关注我的博客,更多精品知识合集 一.读写锁 在我的<java并发编程>上一篇文章中为大家介绍了<ReentrantLock读写锁> ...

  8. 多线程并发编程之显示锁ReentrantLock和读写锁

    在Java5.0之前,只有synchronized(内置锁)和volatile. Java5.0后引入了显示锁ReentrantLock. ReentrantLock概况 ReentrantLock是 ...

  9. Linux程序设计学习笔记----多线程编程线程同步机制之相互排斥量(锁)与读写锁

    相互排斥锁通信机制 基本原理 相互排斥锁以排他方式防止共享数据被并发訪问,相互排斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个相互排斥锁逻辑上绑定之后,对该资源的訪问操作例如以下: ...

随机推荐

  1. 不删除记录的表CRUD的常见处置

    为什么不删除记录,因为这些记录只是暂时不用了,以后还是有可能会用到的,比如说统计:另外一些主键外键依赖级联删除的场合也不好真删的,容易批量删除.真删了就不容易恢复回来了. 一般做法是,增加一个avai ...

  2. C5:单例模式 Singleton

    保证一个类仅有一个实例,并提供一个访问它的全局访问点. 应用场景:A.一个无状态的类使用单例,可以节省内存B.全局或配置类(其实这个也是无状态的)C.脚本或程序从运行开始到结束,仅需要一个实例来保证数 ...

  3. psql命令行快速参考

    psql的命令语法是: psql [options] [dbname [username]] psql命令行选项以及它们的意思在表1-1中列出.使用以下命令可以看到psql完整的选项列表: $ psq ...

  4. 在eclipse中使用Maven建web工程的两种方式

    Eclipse版本:Neon Release (4.6.0) Maven版本:3.3.9 第一种方式: 右键新建maven工程,勾选创建一个简单工程 填入信息,注意打包方式要改为war 点击完成,创建 ...

  5. UUID(即GUID)

    UUID(GUID)是Cocoa Touch提供的一种生成唯一标识的机制.类型为CFUUIDRef的对象可以代表UUID,UUID是基于当前时间.计数器和硬件标识(通常是以太网卡的MAC地址)等数据计 ...

  6. php 记录图片浏览次数次数

    <?php $url='http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING']; $la ...

  7. webstore 与 热编译的配置冲突

    这个勾去掉就会自动编译了!

  8. SVN 创建仓库操作

    服务端安装完成后 1.创建一个存放仓库的文件夹(这里在home目录创建) #mkdir svnRepo #cd svnRepo/ 创建一个仓库 (写全路径) # svnadmin create /ro ...

  9. Android Developer:合并清单文件

    使用Android Studio而且基于Gradle构建.每一个App能在多个位置包括清单文件,比如在src/main文件夹下productFlavor.库.Android ARchive(AAR) ...

  10. MySQL中in(常量列表)的执行计划

    我们在写sql的时候,经常用到in,in后面跟一堆常量列表,如id.有人说in的效率很高,而有人说很低:有人说in能使用索引,还有人说in不能使用索引... 到底是一个怎样的情况呢?我们分析以下几种情 ...