在谈到并发性和C++11内存模型时,Herb给出了非法优化的例子。
http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2
从幻灯片第17分钟开始:
void f(vector<widget>& v) {
if(v.length()>0) xMutex.lock();
for(int i = 0; i < v.length(); ++i)
++x; // write is conditional
if(v.length()>0) xMutex.unlock();
}“一个很有可能(如果有很大缺陷的)中央回路的转换:”
r1 = x;
for(int i = 0; i < v.length(); ++i)
++r1; // oops: write is not conditional
x = r1;他解释说:"...this写是没有条件的,即使doOptionalWork是假的,它也会在每次执行时发生,这会注入一个不受互斥锁保护的写入,从而注入一个竞赛……“
为什么他说发明的写不受互斥锁的保护?我理解如下所描述的全部转换。
// "optimized" version 1
void f(vector<widget>& v) {
if(v.length() > 0) xMutex.lock()
r1 = x;
for(int i = 0; i < v.length(); ++i)
++r1;
x = r1;
if(v.length() > 0) xMutex.unlock();
}但也有可能是这个。
// "optimized" version 2
void f(vector<widget>& v) {
if(v.length() > 0) xMutex.lock()
r1 = x;
for(int i = 0; i < v.length(); ++i)
++r1;
if(v.length() > 0) xMutex.unlock();
x = r1;
}很明显,版本2不是线程安全,但我不确定版本1。版本1线程安全吗?如果在游戏中没有其他写到x的行怎么办?
刚才我开始输入“v.length()是0还是它不是.”意识到在一个多线程的世界里,即使是重言片语也会让我失望。我不知道从哪里开始推理这件事。
发布于 2014-06-29 20:12:10
只有当向量中有某种东西时,才使用互斥。在两个空向量上同时运行此方法会导致数据竞争,因为我们根本没有锁定,但是我们写到x。
发布于 2014-06-29 20:15:34
假设有另一个线程执行以下代码:
xMutex.lock()
++x;
xMutex.unlock();如果上述代码与(转换的)函数f同时执行,则x的增量可能会丢失,尽管在源代码级别上这是不可能的。
发布于 2014-06-29 20:44:08
mutex. lock()函数调用是锁互斥对象的方法。互斥锁是一个互斥锁,只允许一个调用方调用lock()并返回。订阅呼叫者会阻塞,等待原始呼叫者呼叫unlock()。
它是“相互排斥的”,因为只允许一个线程获得锁。
这是互斥的定义。
在您发布的代码中,第二个块没有用lock()和unlock()调用包装增量循环。
这意味着调用更改循环中修改的变量的函数的两个线程将相互执行。一个可以在紧接(或之后)之前写入变量,另一个循环则读取该变量。代码期望变量与函数一致,因此函数的行为将是不正确的。
https://stackoverflow.com/questions/24479803
复制相似问题