| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 《C++标准库》学习笔记 — STL — 并发 — 线程同步与并发 — mutex 与 lock -> 正文阅读 |
|
[C++知识库]《C++标准库》学习笔记 — STL — 并发 — 线程同步与并发 — mutex 与 lock |
《C++标准库》学习笔记 — STL — 并发 — 线程同步与并发一、线程同步与并发并发问题1、出错情况(1)未同步化的数据访问并行运行的两个线程分别读和写同一个数据。
上述代码在单线程中的运行可以满足其语义。然而,在多线程情况中,我们不能保证在 if 判断之后和 front 调用之前,该 vector 没有被改变。 (2)写至半途的数据如果两个线程分别执行下面两段代码:
打印的值是不确定的,有可能是-1,有可能是0,有可能是在某次写入只写入一半时的数据。C++标准并不保证对于基本类型的写入是原子操作。 (3)重新安排的语句考虑下面三段代码(第一段为全局变量声明,剩下两段分别为两个线程中运行的代码):
如果代码按照我们书写的顺序执行,我们确实可以认为在调用 foo() 函数时,其参数为42。然而,实际情况却是编译器或硬件可能会调整语句的执行顺序。因为C++标准只要求编译的代码在单一线程内的可观测行为正确。 2、解决问题需要的特性
C++标准库所提供的办法包括:
3、C++并发的支持在C++11之前,语言本身和标准库都不支持并发,虽然编译器实现可以对此提供某些支持。C++11中,不论内核语言或标准都加强支持并发编程。 对于语言本身:
标准库提供以下保证:
二、Mutex 和 LockMutex 全名 mutual exclusion,是个 object,用来协助采取独占地排他方式控制”对资源的并发访问“。这里所谓“资源”可能是个 object,或多个 object 的组合。为了获得独占式的资源访问能力,相应的线程锁定 mutex,这样可以防止其它线程也锁定 mutex。 1、使用 mutex 和 lock下面的代码展示了在两个线程中,互斥体的使用:
这里需要注意,mutex 的构造并不和某个对象绑定。其和一个或一组对象的绑定是语义上的,体现在代码中。 但是,这种使用较为麻烦。有时我们会在一个线程的多处进行退出;有时线程中会抛出异常。如果在任何一个地方我们忘记解锁,就会造成死锁的结果。因此,我们需要遵守 RAII 守则(可以参考 《Effictive C++》学习笔记 — 资源管理)。在标准库中,我们可以使用 lock_guard 实现这样的功能:
如果不使用这种方式,我们可能需要使用 goto 这种非结构化编程的方式。 2、recursive lock有时候,递归锁定是必要的。典型例子是数据库接口,它在每个公有函数内放一个 mutex 并取得 lock,以防止数据竞争带来的对象状态异常。例如:
但是如果有一个接口想要调用另外一个接口,将会造成死锁:
在这种情况下,我们可以使用 recursive lock。这种 mutex 允许我们多次 lock,只要 unlock 和 lock 是一一对应的。 3、尝试性的 lock 和带时间性的 lock有时候程序想要获得一个 lock 但如果不可能成功的话,它不想永远阻塞。针对这种情况,我们可以使用 try_lock(),它试图取得一个 lock,成功就返回 true,否则就返回 false。 为了仍然能够使用 lock_guard (使当前作用域的任何出口都会自动解锁),我们可以传一个额外的实参 adopt_lock 给其构造函数,其作用在于不再构造时加锁:
为了等待特定长度的时间,我们可以选用 timed_mutex:
4、处理多个 lock不同的锁可能会控制着不同的资源。但是,在某些事务中,可能我们需要按某种固定的顺序访问这些资源并在它们之间进行数据传递。因此,我们需要同时加多个锁。C++标准库中提供了全局 lock 函数来实现这种功能:
类似地,我们可以使用全局 try_lock() 函数对多个互斥体尝试加锁。该函数在所有加锁都成功的情况下会返回-1,否则返回加锁失败的 index,该次序与参数次序一致。 5、unique_lock除了使用 lock_guard,C++标准库还提供了 unique_lock。该类除了支持 RAII,还支持我们指定何时以及如何解锁。因此,一个 unique_lock 对象可能拥有一个锁住的互斥体,也可能没有。该类提供的方法如下: 6、shared_mutex 和 shared_lockshared_mutex 是C++17中提出的一种互斥体。这种互斥体类似读写锁,提供了两种不同级别的访问:使用 lock() 会阻止所有线程其他线程锁定互斥体;使用 shared_lock() 可以在多线程中同时访问数据:
7、只调用一次有时候某些数据在第一次被初始化后,其他线程直接使用该数据即可。以单例的懒汉式为例。如果我们想要正确的在多线程情况下实现懒汉式,需要在判断静态对象是否为空之前增加锁。在C++中,我们可以使用 once_flag 和 call_once 实现此功能:
|
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 11:51:34- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |