当互斥锁/解锁深埋在函数调用中时,我是否需要栅栏或屏障?

时间:2013-03-30 19:52:38

标签: c++ concurrency mutex critical-section

我最近了解到编译器会通过重新排列指令来优化您的代码,并且这可以通过使用障碍来控制。

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(),因为它都是虚拟的。

这会导致错误吗?我是否需要以某种方式手动指定障碍?

1 个答案:

答案 0 :(得分:6)

重新排序说明在各个级别完成。最明显的一个是编译器,一个不那么明显的是CPU(它在运行中)。但是,同步函数几乎总是一个栅栏,它可以防止栅栏前后的指令重新排序。

因此,如果你的虚拟lock调用pthread_mutex_*(),那么你的虚拟函数就会包含一个围栏。

所以简短的回答是:不,它不会导致错误。

还有volatile关键字,它依赖于平台也可以生成栅栏。但是,使用volatile关键字会使检测这些栅栏变得更加困难,因为每次使用易失性的函数或变量时都会引入栅栏。所以建议您使用平台的同步功能。

您需要了解防护的唯一时间是您不使用并发对象来执行同步(例如使用bool而不是互斥锁)。