苏州建网站哪家,外国人做的关于中国的视频网站吗,尺寸在线做图网站,第一ppt网站官网前文我们通过原子操作实战实现了无锁队列#xff0c;今天完善一下无锁的原子操作剩余的知识#xff0c;包括Relaese和Acquire内存序在什么情况下是存在危险的#xff0c;以及我们可以利用栅栏机制实现同步等等。
线程可见顺序
我们提到过除了memory_order_seq_cst顺序#…前文我们通过原子操作实战实现了无锁队列今天完善一下无锁的原子操作剩余的知识包括Relaese和Acquire内存序在什么情况下是存在危险的以及我们可以利用栅栏机制实现同步等等。
线程可见顺序
我们提到过除了memory_order_seq_cst顺序其他的顺序都不能保证原子变量修改的值在其他多线程中看到的顺序是一致的。
但是可以通过同步机制保证一个线程对原子变量的修改对另一个原子变量可见。通过“Syncronizes With” 的方式达到先行的效果。
但是我们说的先行是指 “A Syncronizes With B ” 如果A 的结果被B读取则A 先行于B。
有时候我们线程1对A的store操作采用release内存序而线程2对B的load采用acquire内存序并不能保证A 一定比 B先执行。因为两个线程并行执行无法确定先后顺序我们指的先行不过是说如果B读取了A操作的结果则称A先行于B。
我们看下面的一段案例
#include iostream
#include atomic
#include thread
#include cassert
std::atomicbool x, y;
std::atomicint z;
void write_x()
{x.store(true, std::memory_order_release); //1
}
void write_y()
{y.store(true, std::memory_order_release); //2
}
void read_x_then_y()
{while (!x.load(std::memory_order_acquire));if (y.load(std::memory_order_acquire)) //3z;
}
void read_y_then_x()
{while (!y.load(std::memory_order_acquire));if (x.load(std::memory_order_acquire)) //4z;
}
// 我们写一个函数测试函数TestAR中初始化x和y为false 启动4个线程a,b,c,d分别执行write_x, write_y, read_x_then_y, read_y_then_x.
void TestAR()
{x false;y false;z 0;std::thread a(write_x);std::thread b(write_y);std::thread c(read_x_then_y);std::thread d(read_y_then_x);a.join();b.join();c.join();d.join();assert(z.load() ! 0); //5std::cout z value is z.load() std::endl;
}有的读者可能会觉5处的断言不会被触发他们认为c和d肯定会有一个线程对z执行操作。他们的思路是这样的。
1 如果c线程执行read_x_then_y没有对z执行加加操作那么说明c线程读取的x值为true, y值为false。
2 之后d线程读取时如果保证执行到4处说明y为true等d线程执行4处代码时x必然为true。
3 他们的理解是如果x先被store为truey后被store为truec线程看到y为false时x已经为true了那么d线程y为true时x也早就为true了所以z一定会执行加加操作。
上述理解是不正确的我们提到过即便是releas和acquire顺序也不能保证多个线程看到的一个变量的值是一致的更不能保证看到的多个变量的值是一致的。
变量x和y的载入操作3和4有可能都读取false值与宽松次序的情况一样因此有可能令断言触发错误。变量x和y分别由不同线程写出所以两个释放操作都不会影响到对方线程。
看下图即线程a执行了但是线程d没有看见
线程b执行了但是线程c没有看见
栅栏
有时候我们可以通过栅栏保证指令编排顺序。
看下面一段代码
#include atomic
#include thread
#include assert.h
std::atomicbool x,y;
std::atomicint z;
void write_x_then_y()
{x.store(true,std::memory_order_relaxed); // 1y.store(true,std::memory_order_relaxed); // 2
}
void read_y_then_x()
{while(!y.load(std::memory_order_relaxed)); // 3if(x.load(std::memory_order_relaxed)) // 4z;
}
int main()
{xfalse;yfalse;z0;std::thread a(write_x_then_y);std::thread b(read_y_then_x);a.join();b.join();assert(z.load()!0); //5
}