我是否需要使用原子<>如果已经受到互斥锁的保护

Do I need to use atomic<> if already guard by mutex

本文关键字:保护 如果 gt lt 是否      更新时间:2023-10-16

给定本文中的代码,只使用atomic<>mutex来实现Semaphore

我只是好奇,既然count已经被updateMutex保护了,那么atomic<>有必要吗?

struct Semaphore {
int size;
atomic<int> count;
mutex updateMutex;
Semaphore(int n) : size(n) { count.store(0); }
void aquire() {
while (1) {
while (count >= size) {}
updateMutex.lock();
if (count >= size) {
updateMutex.unlock();
continue;
}
++count;
updateMutex.unlock();
break;
}
}
void release() {
updateMutex.lock();
if (count > 0) {
--count;
} // else log err
updateMutex.unlock();
}
};

如果没有atomic,我认为构造函数会出现同步问题。如果在构造之后其他线程正在使用count的赋值,则该赋值可能不可见。

如果是,那么size呢?它是否也需要受到atomic<>的保护?

或者atomic<>是完全无用的,因为无论其他线程何时使用sizecount都是可见的。

谢谢!

有多个问题被问到。所有这些都需要理解底层概念:如果一个对象是由至少一个线程写入的,而另一个线程访问(读取或写入)该线程,并且写入和访问不同步,那么就存在数据竞赛。数据竞赛的正式定义见1.10[介绍.多线程]第21段:

如果程序在不同线程中包含两个冲突的操作,则程序的执行包含数据竞赛,其中至少一个操作不是原子操作,并且两个操作都不在另一个之前发生。[…]

包含数据争用的程序具有未定义的行为,即程序需要确保它没有数据争用。现在回答不同的问题:

  1. 是否有必要在构造函数中使用同步?

    这取决于对象在构建过程中是否可以由不同的线程同时访问。我能想象的对正在构建的对象的并发访问的唯一情况是在静态初始化期间,其中多个线程已经开始访问共享对象。由于对全局对象的构造顺序的弱约束,我无法想象无论如何都会使用全局对象,并且函数局部static对象的构造是由实现同步的。否则,我希望使用适当的同步机制在线程之间共享对对象的引用。也就是说,我会设计系统,使构造函数不需要同步。

  2. 已经有锁了。这是否意味着count不一定是原子。

    由于count是在获得锁之前在acquire()函数中访问的,因此这将是对另一个线程写入的对象的非同步访问,即,您将有数据竞争,因此会有未定义的行为。count必须是原子的。

  3. size也需要同步吗。

    size成员仅在Semaphore的构造函数中修改,通过实际使其成为const成员来强制执行这一点可能是合理的。假设在构建过程中没有同时访问对象(请参见1。在访问CCD_ 22时不存在数据竞争的可能性。

请注意,您不应该真正无保护地使用互斥对象的lock()unlock()成员。相反,您应该使用std::lock_guard<std::mutex>std::unique_lock<std::mutex>,可能带有辅助块。这两个类保证了获取的锁将始终被释放。我还想知道,繁忙地等待信号量获取锁是否是正确的方法。

我认为count成为atomic<int>的真正原因是在mutex保护区外的aquire()读取

while (count >= size) {}

在没有atomic的情况下,编译可以假设读取一次就足够了,并且不会轮询其他线程中更改的值。

是。有一个理论风险:

count = 0;

则构造函数中的任何一个都不会被在另一个CPU上运行的不同线程及时观察到以用于对CCD_ 33或CCD_。发生这种情况的可能性可能非常小,因为为了使用信号量对象,构造函数必须完成,并且需要另一个线程以某种方式获取该对象。

也就是说,count占用的内存的另一个CPU视图将不会在CPU之间同步,并且另一个可以读取旧的(例如未初始化的)值。

默认情况下,在这里使用std::atomic<int>会在负载周围生成内存屏障(在本例中是通过过载运算符)并进行存储。默认情况下,这是极端保守的。

您也可以在构造函数中锁定和解锁互斥对象以获得相同的效果,但这甚至更昂贵。

必须说,这是实现计数信号量的一种非常糟糕的方式——但这毕竟是一个采访问题,因此有很多方面。

相关文章: