我不明白为什么有必要用互斥体保护单指令 setter

I do not understand why it is necessary to protect a single-instruction setter with a mutex

我有一个源代码可以做这样的事情:

void setX(int x) {
  pthread_mutex_lock(m_lock);
  m_x = x;
  pthread_mutex_unlock(m_lock);
}

该方法由多个线程同时执行。

我读到有必要用互斥锁保护它以使其线程安全,但我不明白为什么这是必要的。

据我了解,由于该方法只执行 一条指令,因此无论您是否使用互斥锁,它都将始终是原子的(线程安全的)。

所以,我的问题是:上面的方法在没有互斥锁的情况下是否可以通过任何方式生成竞争条件?

这取决于上下文。在可能 most languages/systems 中,将 int 值分配给字段是一个 atomic 操作.

但理论上,这并不能保证。如果您的系统只能处理 8 位字节,则分配 2 或 4 字节的 int 值将不是原子的!

并且一旦您将 variable/field 的类型从 int 更改为 say long,无论如何所有赌注都会取消。从这个意义上说,上面的代码简直是过分了"conservative"。但它有一个优点:如果您决定将 field/parameter 的类型更改为无法自动分配的类型 - 无需进一步更改。

因此:您是对的 - 此处不需要使用互斥锁。但这也没有坏处(可能除了允许死锁或由于增加获取锁的需要而影响性能)。

互斥的原因可能是为了确保分配对其他线程可见。我不知道你的例子中是 C 还是 C++ 代码,我也不知道 C 或 C++ 是什么年代的代码。

在早期版本的 C 和 C++ 中,语言的 内存模型 是实现定义的行为,但在更高版本中,语言规范规定了内存模型,我相信这在某种程度上是就像 Java 程序的内存模型。

在Java中,如果线程A给一个普通的int变量赋值而没有使用任何类型的锁,然后线程B随后检查这个变量,同样没有锁,那么线程B可以看到线程 A 分配的值,也可以看到以前的值。无法保证线程 B 何时(甚至 if)能够看到新值。

如果线程使用互斥锁,情况就会改变。在这种情况下,规则是在线程 B 锁定同一个互斥锁后,线程 A 在解锁互斥锁之前写入变量的任何内容都将对线程 B 可见。