简单数据类型的互斥量

Mutex for simple data types

我对并发还很陌生,我在决定如何使用互斥体时遇到了麻烦。目前,它们散布在我的两个线程交互的代码中。这样使用互斥锁合适吗?

class Foo
{
public:
    void SetMember(int n) {  AcquireMutex(..); n_ = n; ReleaseMutex(...);}
private:
   Thread()
   {
      while(1)
      {
         AcquireMutex(..);
         // Do something with n_
         ReleaseMutex(...);
       }
   }
};

我有很多数据成员可以通过不同的线程从外部读取和设置,我发现跟踪所有互斥锁的获取和释放是一件令人头疼的事情。

不保证原始类型的变异是线程安全的,或者更具体地说是原子的。事实上,如果您查看 <atomic>,您会注意到有几个专业,包括 std::atomic_int.

来自cppreference

Objects of atomic types are the only C++ objects that are free from data races; that is, if one thread writes to an atomic object while another thread reads from it, the behavior is well-defined.

为了具体回答您关于使用互斥锁的问题,是的,您在示例中使用互斥锁没有问题。通常,您希望尽可能短地持有互斥量。换句话说,如果你有一个做很多工作的函数,只锁定非线程安全代码周围的互斥锁,然后一旦代码是线程安全的就解锁它。

这种互斥的做法很幼稚,并不能避免死锁和其他并发问题。

您必须明确识别代码中两个进程同时访问会导致问题的位置,并在关键部分保护它们。并且你必须确保你不会让两个进程启动一个操作,因为另一个进程他们无法完成。

在其他地方,可能不需要保护,激活互斥量就太过分了。

很多时候,原子性不是单个变量所必需的,而是一组耦合变量所必需的。