互斥锁和读写锁的区别

原文地址:http://blog.csdn.NET/u012884354/article/details/46691761

相交进程之间的关系主要有两种,同步与互斥。

所谓互斥,是指散布在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行。

所谓同步,是指散布在不同进程之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。
  显然,同步是一种更为复杂的互斥,而互斥是一种特殊的同步。
  也就是说互斥是两个线程之间不可以同时运行,他们会相互排斥,必须等待一个线程运行完毕,另一个才能运行,而同步也是不能同时运行,但他是必须要安照某种次序来运行相应的线程(也是一种互斥)!
  总结:互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
  同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

[html] view plaincopy
  1. 读写锁特点:  
  2. 1)多个读者可以同时进行读  
  3. 2)写者必须互斥(只允许一个写者写,也不能读者写者同时进行)  
  4. 3)写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)  
  5.    
  6. 互斥锁特点:  
  7.   一次只能一个线程拥有互斥锁,其他线程只有等待  
  8.   
  9. 互斥锁  
  10. pthread_mutex_init()  
  11. pthread_mutex_lock()  
  12. pthread_mutex_unlock()  

  13. 读写锁  
  14. pthread_rwlock_init()  
  15. pthread_rwlock_rdlock()  
  16. pthread_rwlock_wrlock()  
  17. pthread_rwlock_unlock()  

  18. 条件变量  
  19. pthread_cond_init()  
  20. pthread_cond_wait()  
  21. pthread_cond_signal()  


条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法。

举个简单的例子,应用程序A中包含两个线程t1和t2。t1需要在bool变量test_cond为true时才能继续执行,而test_cond的值是由t2来改变的,这种情况下,如何来写程序呢?可供选择的方案有两种:

  • 第一种是t1定时的去轮询变量test_cond,如果test_cond为false,则继续休眠;如果test_cond为true,则开始执行。
  • 第二种就是上面提到的条件变量,t1在test_cond为false时调用cond_wait进行等待,t2在改变test_cond的值后,调用cond_signal,唤醒在等待中的t1,告诉t1 test_cond的值变了,这样t1便可继续往下执行。

          很明显,上面两种方案中,第二种方案是比较优的。在第一种方案中,在每次轮询时,如果t1休眠的时间比较短,会导致cpu浪费很厉害;如果t1休眠的时间比较长,又会导致应用逻辑处理不够及时,致使应用程序性能下降。第二种方案就是为了解决轮询的弊端而生的。然而条件变量在使用的过程中,比较容易出错,如何用得不正确的话,会适得其反的,接下来,我将详细分析如何来使用条件变量,希望能够给在使用条件变量过程中遇到问题的朋友有所帮助。
          在开始介绍之前,需要说明一下,在接下来的介绍中,需要用到互斥锁和条件变量相关的内容,在这里我以Linux下的pthread_mutex_t为互斥锁类型,pthread_cond_t为条件变量类型来进行介绍,对pthread不熟的朋友,可以参考一下linux下的manual。
          1. 下面是把刚开始举的例子翻译后的程序:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    pthread_mutex_t mutex;  ///< 互斥锁
    pthread_cond_t  cond;   ///< 条件变量
    bool test_cond = false;
    /// TODO 初始化mutex和cond/// thread 1:
    pthread_mutex_lock(&mutex);            ///< 1
    while (!test_cond)
    {pthread_cond_wait(&cond, &mutex);  ///< 2,3
    }
    pthread_mutex_unlock(&mutex);          ///< 4
    RunThread1Func();/// thread 2:
    pthread_mutex_lock(&mutex);            ///< 5
    test_cond = true;
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);          ///< 6/// TODO 销毁mutex和cond

          通过上面的例子,下面我来介绍一下条件变量在使用过程中需要注意的几点(也是比较容易出错的):
          (1)条件变量的使用过程中,最为关键的一点是互斥锁的使用。细心的朋友应该发现了,我在上面的例子中标了1、2、3、4、5、6个标号。在这里1、4、5、6都是正常的lock/unlock,2、3是需要特别说明的。2是进入pthread_cond_wait后的,pthread_cond_wait调的pthread_mutex_unlock,这样做的目的是为了保证在thread1阻塞wait后,thread2获取同一把锁mutex的时候,能够正常获取(即5,6)。3是thread1被唤醒后,要退出pthead_cond_wait之前,pthread_cond_wait调的pthread_mutex_lock,这样做的目的是为了把mutex的控制权还给调用pthread_cond_wait的线程(即thread1)。整理一下基本的时序为:

    1
    2
    3
    thread 1 lock->thread 1 wait-> thread 1 unlock(in wait)
    ->thread 2 lock->thread 2 signal->thread 2 unlock
    ->thread 1 lock(in wait)->thread 1 unlock

          (2)条件变量使用的过程中,通常会加一个bool或者int的值test_cond来配合使用。这里需要注意的一点是一定要在signal之前来改变test_cond,这样才能保证wait的线程被唤醒后,能够取到正确的test_cond的值,否则后果是不可预测的。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458539.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JSP EL表达式使用

为什么80%的码农都做不了架构师&#xff1f;>>> ##1.EL全名为Expression Language out.print(str) <%str%> ${str}例子&#xff1a; Hi! <%username%> 和 Hi! ${username}是一样的 只要是支持servlet2.4/jsp2.0的Container就都可以在jsp网页中直接使用e…

eclipse 中 Android sdk 无法更新的问题

诶&#xff0c;真是麻烦&#xff0c;想下个东西都下不了。我也好久没折腾过这个了&#xff0c;在家的电脑是早就下载好了的&#xff0c;然后如今又须要下载一份。下不到。网上搜到了资料&#xff0c;记录下来&#xff1a; 第一种方法:sdk manager - tools - option 选择强制 xx…

iOS10 xcode8 分页请求MJRefresh崩溃问题

MJRefresh出现崩溃现象 解决办法&#xff1a;类库增加判断 if (range.location ! NSNotFound) { language [language substringToIndex:range.location]; }

网络编程学习笔记一:Socket编程

from: http://blog.csdn.net/gneveek/article/details/8699198 “一切皆Socket&#xff01;” 话虽些许夸张&#xff0c;但是事实也是&#xff0c;现在的网络编程几乎都是用的socket。 ——有感于实际编程和开源项目研究。 我们深谙信息交流的价值&#xff0c;那网络中进程之间…

JavaScript原生对象常用方法总结

这是4年前学习JavaScript基础的学习笔记&#xff0c;当初是照着W3School教程学习的&#xff0c;4年恍然如云烟&#xff0c;仿佛还在昨天。现发布与此&#xff0c;留作纪念&#xff0c;纪念那段不悔的青葱岁月。下面都是我学习W3C School教程中有关JavaScript写的学习笔记&#…

[delphi]修改indy源码后重新编译

http://blog.csdn.net/nerdy/article/details/8702568 虽然indy有一身的毛病&#xff0c;但是一般情况下使用起来还是多方便的。 今天在做一个使用到indy的程序的时候&#xff0c;发现无论你怎么修改idhttp.request.accept-encoding&#xff0c;他都会在其后添加一个值 identit…

xcode8 崩溃问题

【1】、Xcode8代码出现ubsystem: com.apple.UIKit, category: HIDEventFiltered, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0 2016-09-14 17:18:…

前端工具--less篇

前端工具–less篇 less 中文网http://www.bootcss.com/p/lesscss/ 常见错误及解决&#xff1a; sublime text 3 安装less2css保存less出现错误 未安装这个 npm install -g less-plugin-clean-css 未安装这个 npm install less -gd less语法 LESS 做为 CSS 的一种形式的扩展&a…

从static变量导出问题解析 __declspec(dllexport) 和 __declspec(dllimport)的作用

这段时间要把tinyxml从静态库弄成动态库&#xff0c;要用到__declspec(dllexport)和__declspec(dllimport)来导出dll和lib文件。终于弄明白了export和import的作用&#xff0c;下面从使用的角度来说明一下他们的功能。 首先要知道&#xff0c;头文件是C的接口文件&#xff0c;不…

4月26日作业

2016年4月26日作业 一、项目整体绩效评估1、*三E审计是什么的合称&#xff1f;&#xff08;记&#xff09; 答&#xff1a;经济审计&#xff0c;效率审计和效果审计2、霍尔三维结构是从哪三个方面考察系统工程的工作过程的&#xff1f; 答&#xff1a;逻辑&#xff0c;时间和知…

xcode8 快捷键失效

因为苹果解决xcode ghost,把插件屏蔽了。 解决方法: 命令运行&#xff1a; sudo /usr/libexec/xpccachectl 然后必须重启电脑后生效

CAS单点登录配置[3]:服务器端配置

在准备工作&#xff0c;证书生成等工作完成后&#xff0c;本篇介绍服务器端的配置。 JDK配置 1我们将生成的cacerts文件分别拷贝到JDK目录下的jre/lib/security目录下及JRE对应的目录中&#xff0c;如果之前存在此文件&#xff0c;请替换&#xff1b; ENDTomcat配置 1Step 1:将…

DLL动态链接库的工作原理

"动态链接"这几字指明了DLLs是如何工作的。 对于常规的函数库&#xff0c;链接器从中拷贝它需要的所有库函数&#xff0c;并把确切的函数地址传送给调用这些函数的程序。 而对于DLLs&#xff0c;函数储存在一个独立的动态链接库文件中。在创建Windows程序时&#xff…

remind程序

2019独角兽企业重金招聘Python工程师标准>>> 用了两个定时器。一个控制刷新时间&#xff0c;一个控制响铃。 定时器响应函数Timer: int wk; if(nIDEvent1) { CTime tCTime::GetCurrentTime(); wkt.GetDayOfWeek()-1; m_mnt.Format("%Y 年 …

查看手机是否安装微信客户端

if (![[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:"weixin://"]] ) {[wcatBtn setHidden:YES];}

Caffe学习系列(7):solver及其配置

solver算是caffe的核心的核心&#xff0c;它协调着整个模型的运作。caffe程序运行必带的一个参数就是solver配置文件。运行代码一般为 # caffe train --solver*_slover.prototxt 在Deep Learning中&#xff0c;往往loss function是非凸的&#xff0c;没有解析解&#xff0c;我们…

Qt DLL总结-创建及调用QT的 DLL

目录 Qt DLL总结【一】-链接库预备知识 Qt DLL总结【二】-创建及调用QT的 DLL Qt DLL总结【三】-VS2008Qt 使用QPluginLoader访问DLL 开发环境&#xff1a;VS2008Qt4.7.4 最近看了不少Qt的DLL例子&#xff0c;总结一下如何创建和调用QT 动态链接库。 先讲一下对QT动态链接库的…

Unable to install pirate

真机测试的时候&#xff0c;报这个错误&#xff0c;主要原因就是证书的问题 xcode7以上进行的真机测试&#xff0c;可以没有使用证书&#xff0c;xcode可以进行的傻瓜操作帮助我们完成真机测试&#xff0c;但是今天我进行真机测试的时候报这个错误&#xff0c;同时xcode也不进…

memmove 对同一个指针不操作

memmove 对同一个指针不操作&#xff0c;所以调用memmove之前不用比较两个指针是否相同 void CTestDLLDlg::OnBnClickedButton6() {const int size 999999;char* data new char[size];memset(data, 1, size - 1);char* data1 new char[size];memset(data1, a, size - 1);clo…

.Net JIT

.Net JIT(转) JIT 转载于:https://www.cnblogs.com/HelloMyWorld/p/5501135.html