《C++标准库》学习笔记 — STL — 并发 — 线程同步与并发 — mutex 与 lock

一、线程同步与并发并发问题

1、出错情况

(1)未同步化的数据访问

并行运行的两个线程分别读和写同一个数据。

std:;vector<int> vec;
if (!vec.empty())
{
   
	std::cout << v.front() << std::endl;
}

上述代码在单线程中的运行可以满足其语义。然而,在多线程情况中,我们不能保证在 if 判断之后和 front 调用之前,该 vector 没有被改变。

(2)写至半途的数据

如果两个线程分别执行下面两段代码:

long long x = 0;
x = -1;
std::cout << x;

打印的值是不确定的,有可能是-1,有可能是0,有可能是在某次写入只写入一半时的数据。C++标准并不保证对于基本类型的写入是原子操作

(3)重新安排的语句

考虑下面三段代码(第一段为全局变量声明,剩下两段分别为两个线程中运行的代码):

long data;
bool readyFlag = false;
data = 42;
readyFlag = true;
while (!readyFlag)
{
   
	;
}

foo(data);

如果代码按照我们书写的顺序执行,我们确实可以认为在调用 foo() 函数时,其参数为42。然而,实际情况却是编译器或硬件可能会调整语句的执行顺序。因为C++标准只要求编译的代码在单一线程内的可观测行为正确

2、解决问题需要的特性

  • 原子性:对共享变量的访问应该是独占式,不应该被其他线程打断的。因此,线程之间不应该读取到变量的中间状态。
  • 次序:我们需要保证某些语句的执行次序。

C++标准库所提供的办法包括:

  • 使用 futurepromise。它们都保证原子性和次序:一定是在得到结果后才设定共享状态。因此,对于共享状态的读和写不会同时发生。
  • 使用 mutexlock 来处理临界区或保护区。其提供了原子性,使得我们可以实施对于相同资源的读写控制。
  • 使用 conditional variable 有效地某线程等待某个判断式称为真。
  • 使用 atomic data tyoe 确保对变量或对象的访问动作是不可切割的,只要其操作顺序是稳定的。
  • 使用 atomic data tyoe 的低层接口,它允许我们从某种程度上限制某种代码的运行次序。

3、C++并发的支持

在C++11之前,语言本身和标准库都不支持并发,虽然编译器实现可以对此提供某些支持。C++11中,不论内核语言或标准都加强支持并发编程。

对于语言本身:

  • 如今具备了这样一个内存模型,保证当你修改“被不同线程使用的”不同对象时,它们彼此独立。在C++11之前,并不保证“某线程涂写一个char”不会干涉“另一线程涂写另一个char”。
  • 引入新关键字 thread_local,用来定义线程特定的变量和对象。

标准库提供以下保证:

  • 一般而言,多个线程共享同一个程序库对象而其中至少一个线程改动该对象时,可能会导致不明确行为。特别是,当某个线程的对象构造期间,另一个线程使用该对象,会导致不明确行为。析构的情况与之类似。
  • STL容器和适配器中,并发的只读访问是允许的,并发的处理同一容器内的不同元素是可以的。
  • 对标准流进行格式化输入和输出的并发处理是可能的。虽然这可能引发插叙字符(乱序)。这项保证适用于 std::instd::outstd::err,不适用于 string streamfile streamstream buffer
  • atexit()at_quck_exit() 的并发调用是同步的。相同情况适用于 newterminateunexpected handler 的函数。此外,getenv() 的调用也是同步的。
  • 默认分配器的所有成员函数,除了析构函数,其并发处理都是同步的。

二、Mutex 和 Lock

Mutex 全名 mutual exclusion,是个 object,用来协助采取独占地排他方式控制”对资源的并发访问“。这里所谓“资源”可能是个 object,或多个 object 的组合。为了获得独占式的资源访问能力,相应的线程锁定 mutex,这样可以防止其它线程也锁定 mutex

1、使用 mutex 和 lock

下面的代码展示了在两个线程中,互斥体的使用:

// global
int val;
std::mutex valMutex;
// thread1
valMutex.lock();
if (val >= 0
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值