当互斥锁/解锁深埋在函数调用中时,我需要栅栏或屏障或其他东西吗?

Do I need a fence or barrier or something when mutex locks/unlocks are buried deep in function calls?

本文关键字:其他 解锁 函数调用      更新时间:2023-10-16

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

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

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

指令的重新排序是在不同的级别上完成的。最明显的一个是编译器,不太明显的一个是CPU(它是动态的)。然而,同步函数几乎总是一个栅栏,它防止之前和之后的指令被重新排序。

如果你的虚拟lock调用pthread_mutex_*(),那么你的虚拟函数包含一个fence。

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

还有volatile关键字,根据平台的不同,它也可以生成一个fence。但是,使用volatile关键字会使检测这些栅栏变得更加困难,因为每次使用volatile函数或变量时都会引入一个栅栏。因此建议您使用平台的同步功能。

你唯一需要注意的是当你不使用并发对象来执行同步时(比如使用bool代替互斥锁)。