C++线程中的几类锁

  多线程中的锁主要有五类:互斥锁、条件锁、自旋锁、读写锁、递归锁。一般而言,所得功能与性能成反比。而且我们一般不使用递归锁(C++提供std::recursive_mutex),这里不做介绍。

互斥锁

  互斥锁用于控制多个线程对它们之间共享资源互斥访问的一个信号量。也就是说为了避免多个线程在某一时刻同时操作一个共享资源,例如一个全局变量,任何一个线程都要使用初始锁互斥地访问,以避免多个线程同时访问发生错乱。

  在某一时刻只有一个线程可以获得互斥锁,在释放互斥锁之前其它线程都不能获得互斥锁,以阻塞的状态在一个等待队列中等待。

头文件:#include <mutex>

类型:std::std::mutex、std::lock_guard

用法:在C++中,通过构造std::mutex的实例创建互斥单元,调用成员函数lock()来锁定共享资源,调用unlock()来解锁。不过一般不使用这种解决方案,更多的是使用C++标准库中的std::lock_guard类模板,实现了一个互斥量包装程序,提供了一种方便的RAII风格的机制在作用域块中。

关于RAII惯用法的介绍可参考博主的博客:https://blog.csdn.net/qq135595696/article/details/121411724。

示例代码:

#include <iostream>
#include <thread>//C++11线程库是跨平台的
#include <mutex>//C++互斥锁
#include <vector>
#include <windows.h>int g_num = 0;
std::mutex g_mutex;void ThreadFunc(int a)
{cout << "启动线程:" << a << endl;for (int i = 0; i < 1000000; i++){//g_mutex.lock();std::lock_guard<std::mutex> m(g_mutex);//互斥量包装程序g_num++;//g_mutex.unlock();}
}int main()
{for (int i = 0; i < 4; i++){std::thread t(ThreadFunc, i);t.detach();}Sleep(2000);cout << "g_num:" << g_num << endl;return 0;
}//高阶版,将上述main()函数的函数名更改,再更改以下的mainTest()即可执行。两个方法的执行的结果相同,原理也相同。
int mainTest()
{std::vector<std::thread *> ts;for (int i = 0; i < 4; i++){std::thread *t = new std::thread(ThreadFunc, i);//t.detach();ts.push_back(t);}for (auto begin = ts.begin(); begin != ts.end(); begin++)(*begin)->join();Sleep(2000);cout << "g_num:" << g_num << endl;return 0;
}

TIPS:注意std::cout和std::end都是线程不安全的,所以才会出现线程1和线程3在一行,原因就是线程1未执行cout<<endl。CPU的时间片就已经用完了,CPU转移执行线程3后,再执行线程1的cout<<endl。

具体C++11中thread库join和detach的区别可参考:https://blog.csdn.net/qq135595696/article/details/121387692

条件锁

  条件锁就是所谓的条件变量,当某一个线程因为某个条件未满足时可以使用条件变量使该程序处于阻塞状态,一旦条件满足则以“信号量”的方式唤醒一个因为该条件而被阻塞的线程。最为常见的就是在线程池中,初始情况下因为没有任务使得任务队列为空,此时线程池中的线程因为“任务队列为空”这个条件处于阻塞状态。一旦有任务进来,就会以信号量的方式唤醒该线程来处理这个任务。

自旋锁

  互斥锁和条件锁都是比较常见的锁,比较容易理解。接下来用互斥锁和自旋锁的原理相互比较,来理解自旋锁。

  假设我们有一台计算机,该计算机拥有两个处理器core1和core2.现在在这台计算机上运行两个线程:T1和T2,且T1和T2分别在处理器core1和core2上面运行,两个线程之间共享一份公共资源Public。

  首先我们说明互斥锁的工作原理,互斥锁是一种sleep-waiting的锁。假设线程T1访问公共资源Public并获得互斥锁,同时在core1处理器上运行,此时线程T2也想要访问这份公共资源Public(即想要获得互斥锁),但是由于T1正在使用Public使得T2被阻塞。当T2处于阻塞状态时,T2被放入等待队列中,处理器core2会去处理其它的任务而不必一直等待(忙等)。也就是说处理器不会因为线程被阻塞而空闲,它会去处理其它事务。

  然后我们说明自旋锁的工作原理,自旋锁是一种busy-waiting的锁。也就是说,如果T1正在使用Public,而T2也想使用Public,此时T2肯定是得不到这个自旋锁的。与互斥锁相反,此时运行T2的处理器core2会一直不断地循环检查Public使用可用(自旋锁请求),直到获得到这个自旋锁为止。

  从“自旋锁”的名称也可以看出,如果一个线程想要获得一个被使用的自旋锁,那么它会一直占用CPU请求这个自旋锁使得CPU不能去做其它的事情,知道获取这个锁为止,这就是“自旋”的含义。当发生阻塞时,互斥锁可以让CPU去处理其它的事务,但自旋锁让CPU一直不断循环请求获取这个锁。通过比较,我们可以明显的得出结论:“自旋锁”是比较消耗CPU的。

读写锁

  读写锁我们可以借助于“读者-写者”问题进行理解。接下来我们简单说下“读者-写者”问题。

  计算机中某些数据被多个进程共享,对数据库的操作有两种:一种是读操作,就是从数据库中读取数据不会修改数据库中内容;另一种就是写操作,写操作会修改数据库中存放的数据。因此可以得到我们允许在数据库上同时执行多个“读”操作,但是某一时刻只能在数据库上有一个“写”操作来更新数据。这就是简单的读者-写者模型。

参考博客

https://blog.csdn.net/xy_cpp/article/details/81910513

C++线程中的几类锁相关推荐

  1. 线程中这么调用类_这些线程知识总结是真的到位!java开发两年的我看的目瞪口呆

    前言 什么是线程:程序中负责执行的那个东东就叫做线程(执行路线,进程内部的执行序列),或着说是进程的子任务. Java中实现多线程有几种方法 继承Thread类: 实现Runnable接口: 实现Ca ...

  2. 线程中这么调用类_一文学会 Python 多线程编程

    Threading 模块从Python 1.5.2版开始出现,用于增强底层的多线程模块 thread .Threading 模块让操作多线程变得更简单,并且支持程序同时运行多个操作. 注意,Pytho ...

  3. 线程中这么调用类_「手撕面试官」谈谈你对JDK中Executor的理解?

    欢迎关注头条号:Java小野猫 前言 随着当今处理器计算能力愈发强大,可用的核心数量越来越多,各个应用对其实现更高吞吐量的需求的不断增长,多线程 API 变得非常流行.在此背景下,Java自JDK1. ...

  4. python进程和线程中的两个锁

    GIL锁(全局解释器锁) gil锁的作用是:每个进程中同一时间只能有一个进程链接cpu,链接以后,cpu执行100个cpu指令以后,再由别的线程去链接cpu, Rlock锁(可重入锁/递归锁) imp ...

  5. c++线程中的几种锁

    这个是在中兴面试中被面试问到的一个题"你知道线程中的自旋锁么?",我当时一脸懵逼,不知道.回来后整理下,在这里对线程中的锁进行一个学习. 线程之间的锁有:互斥锁.条件锁.自旋锁.读 ...

  6. 【Java 并发编程】线程锁机制 ( 线程安全 | 锁机制 | 类锁 | 对象锁 | 轻量级锁 | 重量级锁 )

    文章目录 一.线程安全 二.锁机制 ( 类锁 | 对象锁 ) 三.锁分类 ( 轻量级锁 | 重量级锁 ) 一.线程安全 多个线程同时访问 同一个共享变量 时 , 只要能保证 数据一致性 , 那么该变量 ...

  7. java中存在对多个对象加锁的情况_Java对象锁和类锁全面解析(多线程synchronized关键字)...

    最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念.最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没 ...

  8. Java 对象锁和类锁全面解析

    2019独角兽企业重金招聘Python工程师标准>>> 最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念. ...

  9. java同步锁synchronized_Java对象锁和类锁全面解析(多线程synchronized关键字)

    本文主要是将synchronized关键字用法作为例子来去解释Java中的对象锁和类锁.特别的是希望能帮大家理清一些概念. 一.synchronized关键字 synchronized关键字有如下两种 ...

  10. Java对象锁和类锁全面解析(多线程synchronized关键字)

    最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念.最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没 ...

最新文章

  1. 前端开发自学之JavaScript——显示当前时间
  2. JavaFX官方教程(十五)之A Xylophone.java
  3. vue2.0 如何自定义组件(vue组件的封装)
  4. 删除行对MySQL序列有这么多影响?
  5. 基于MFC和OpenCV的摄像机定标与立体匹配测试程序
  6. Flink本地安装教程
  7. HDU 6312.Game-博弈-签到题 (2018 Multi-University Training Contest 2 1004)
  8. sphinx系列之中文分词LibMMSeg安装(三)
  9. 接口测试基础——第6篇unittest模块(三)
  10. git 远程删除分支之后 本地分支更新后还在
  11. 格签名困难假设: 最短向量问题SVP
  12. 小程序文档整理之 -- API(开放接口)
  13. hdu 1862 EXCEL排序
  14. windowsPE制作工具
  15. java环境classpath_JAVA中的环境变量配置 PATH CLASSPATH
  16. 使用新路由器有线/无线桥接旧路由器
  17. 最小二乘估计,矩阵求导法(正规方程)全推导
  18. iPhone为什么要登录苹果ID才能下载软件?
  19. 无线产品认证logo
  20. 游戏服务器多少钱一个月 游戏服务器配置怎么选择

热门文章

  1. 【干货】李航老师《统计学习方法》(第2版)清华PPT课件分享
  2. 【分享】自身经历谈一谈自然语言处理领域如何学习?
  3. 详解中文维基百科数据处理流程及脚本代码
  4. 学术杂谈|一篇所有研究生都该读的好文:阳光温热 科研静好!
  5. 互联网核心应用(搜索/推荐/广告)算法峰会
  6. 数据结构与算法python—9.二叉树及python实现
  7. 深度学习2.0-5.tensorflow的基础操作之前向传播(张量)实战
  8. 模型融合之stacking和blending
  9. [论文笔记]Poly-encoders: architectures and pre-training strategies for fast and accurate multi-sentence
  10. 优化理论05----最速下降法、最速下降法思想、python实现