编译器跨互斥边界重新排序代码
Code reordering by compiler across mutex boundaries
考虑以下代码:
int a = 0, b = 0;
boost::mutex m;
a++;
m.lock();
m.unlock();
b++;
锁的作用是告诉编译器"ok, forget about the C++ standard for a moment, I don't care what optimizations it would have allowed if you'd followed that strictly. You must NOT reorder any memory accesses across this boundary"。这是否意味着 a++;
总是发生在 b++;
之前?或者这是否意味着,如果在锁之间有一个语句 s,不要用 a++
或 b++
重新排序?
Baum mit Augen 的评论已经很好地回答了这个问题。
但是,如果 "a" 和 "b" 是 global 变量,并且声明为 volatile,这取决于编译器互斥量强加的内存屏障可以保证 read/write 表达式不会跨边界重新排序。
这意味着读取"b"并发现它已经增加的线程,在此之后执行类似的互斥锁定以施加内存屏障,最后读取"a",保证找到"a" 也被修改了。
MSVC 有这种行为,其他一些编译器也有。
考虑以下代码:
int a = 0, b = 0;
boost::mutex m;
a++;
m.lock();
m.unlock();
b++;
锁的作用是告诉编译器"ok, forget about the C++ standard for a moment, I don't care what optimizations it would have allowed if you'd followed that strictly. You must NOT reorder any memory accesses across this boundary"。这是否意味着 a++;
总是发生在 b++;
之前?或者这是否意味着,如果在锁之间有一个语句 s,不要用 a++
或 b++
重新排序?
Baum mit Augen 的评论已经很好地回答了这个问题。
但是,如果 "a" 和 "b" 是 global 变量,并且声明为 volatile,这取决于编译器互斥量强加的内存屏障可以保证 read/write 表达式不会跨边界重新排序。
这意味着读取"b"并发现它已经增加的线程,在此之后执行类似的互斥锁定以施加内存屏障,最后读取"a",保证找到"a" 也被修改了。
MSVC 有这种行为,其他一些编译器也有。