我最近了解到编译器会通过重新排列指令来优化您的代码,并且这可以通过使用障碍来控制。
IIRC,锁定互斥锁会造成障碍,解锁互斥锁也会成为障碍,使关键部分内的代码不会出现。所以pthread_mutex_lock和pthread_mutex_unlock必须隐含地成为这些“障碍”。如果我有这样的课程,包装我的互斥锁怎么办?
class IMutex {
public:
virtual void lock() = 0;
virtual void unlock() = 0;
};
在我看来,编译器不会知道我在lock()中调用pthread_mutex_lock(),而在unlock()中调用pthread_mutex_unlock(),因为它都是虚拟的。
这会导致错误吗?我是否需要以某种方式手动指定障碍?
答案 0 :(得分:6)
重新排序说明在各个级别完成。最明显的一个是编译器,一个不那么明显的是CPU(它在运行中)。但是,同步函数几乎总是一个栅栏,它可以防止栅栏前后的指令重新排序。
因此,如果你的虚拟lock
调用pthread_mutex_*()
,那么你的虚拟函数就会包含一个围栏。
所以简短的回答是:不,它不会导致错误。
还有volatile关键字,它依赖于平台也可以生成栅栏。但是,使用volatile关键字会使检测这些栅栏变得更加困难,因为每次使用易失性的函数或变量时都会引入栅栏。所以建议您使用平台的同步功能。
您需要了解防护的唯一时间是您不使用并发对象来执行同步(例如使用bool
而不是互斥锁)。