2010-01-22 57 views
5

这里是一些可以从多个线程并行访问的C++代码。它有一个关键部分:用锁重新排列声明

lock.Acquire(); 
current_id = shared_id; 
// small amounts of other code 
shared_id = (shared_id + 1) % max_id; 
lock.Release(); 
// do something with current_id 

锁定变量的类是POSIX互斥体实现的包装。由于模块操作,不可能使用原子操作。

是否有可能带有O3标志的gcc编译器优化了代码,以便在锁之前移动current_id的赋值?

回答

3

可以用O3编译!

除非使用函数属性将函数标记为纯函数,否则编译器将永远不会通过函数调用进行优化。

互斥函数不是纯粹的,所以它与O3一起使用是绝对安全的。

+1

你的意思是“除非函数被标记为纯**或者编译器能够确定它是安全的**。当然,最终结果是一样的,编译器一般不会进行优化,除非它可以验证它是安全的。 – jalf 2010-01-22 18:38:06

+0

如果'current_id'和'shared_id'都是没有逃过当前作用域的局部变量(地址没有给任何其他人,等等),那么优化器可以重新排列这些行,而忽略来自外部函数调用的可能的突变,不过我认为在这里并不是这样, – ephemient 2010-01-22 19:15:36

+0

@ephemient:但是如果它们是本地的而且没有外部的一个人都知道外部函数调用如何修改它们? – Kosi2801 2010-01-24 11:00:40

1

通常编译器不应该进行这种有害的优化。如果您仍然不确定,可以使用volatile关键字来防止对该变量进行优化。

+0

易失性不会阻止所有相关的优化。它可以防止将值缓存到寄存器中,但几乎没有其他值。读/写仍然可以重新排序。 – jalf 2010-01-22 18:37:03

+0

作为Linux内核文档的一部分,关于何时使用volatile的一个很好的方法:http://www.mjmwired.net/kernel/Documentation/volatile-considered-harmful.txt – asveikau 2010-01-22 18:37:57

+0

@jalf:但是编译器是否真正对读/写入,以便它们跨越函数调用边界?赋值和函数调用混合在一起是相当普遍的,如果变量的赋值可以通过函数调用来切换顺序,那么我认为遍地都会有很多问题。 – Kosi2801 2010-01-24 10:58:57