理解原子变量之五:指令重排、memory_order__acquire与memory_order_release

看下面代码:

#include <iostream>
#include <thread>
#include <assert.h>
#include <atomic>

int a = 0;
std::atomic<bool> flag{ false };

void f1()
{
	a = 1;
	flag.store(true, std::memory_order_release);
	//flag.store(true, std::memory_order_relaxed);
}

void f2()
{
	while (!flag.load(std::memory_order_acquire))
	//while (!flag.load(std::memory_order_relaxed))
	{

	}

	assert(a == 1);
}


int main(void)
{
	std::thread t2(f2);
	std::thread t1(f1);
	

	t1.join();
	t2.join();

	return 0;
}

1 memory_order_release要求,在调用memory_order_release之前的所有写操作,不得重排到memory_order_release之后。在上面的代码里,显然a = 1就是写入。

2 memory_order_acquire要求,在调用memory_order_acquire之后的所有读操作,不得重排到memory_order_acquire之前。在上面的代码里,a == 1是对a当前值的判断,当然属于读操作。

3 结合1与2,函数f2的while循环直到flag == true才会跳出,所以跳出之前,f1一定已经将flag.store执行完毕了。那么根据(1)的要求,a=1的操作肯定发生在flag.store之前。于是,while()循环结束后,a=1的操作一定已经发生了。再结合上一篇理解原子变量之四:可见性、memory_order_acquire与 memory_order_release_memory order acquire-CSDN博客的可见性,a的改变一定可以对此时的线程t2可见。

最后,根据(2)的要求,assert(a == 1)一定发生在while之后,因为里面含有flag.load(memory_order_acquire)。所以assert(a == 1)一定可以看到a == 1为真。

最后,建议读一下微信公众号“程序喵大人”的文章《【C++并发系列】第五章:C++ 内存模型在约束什么?》,里面的描述更加全面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值