所有 getter,即 return 一个可能被不同线程修改的变量,是否需要用互斥锁或等效物来保护?

Do all getters, that return a variable potentially modified by a different thread, need to be protected with mutex or equivalent?

让我们假设以下 C 代码片段:

static bool var;

DECLARE_MUTEX(lock);

void mod_set_var(bool v)
{
  mutex_lock(lock);
  var = v;
  mutex_unlock(lock);
}

bool mod_get_var(void)
{
  return var;
}

假设上述函数可以被许多不同的线程访问,并且我们根本不想依赖底层架构的能力。做原子分配等

据我了解,理论上说 mod_get_var 应该用互斥体保护。但是,我无法想象上面的代码可能会导致问题的情况。

我读过 this other post,其中@David Schwartz 揭露了一个灾难的例子。但是,如果 foo j; 是在函数内部本地创建的,则会发生这种情况,但这里的 var 是静态分配的变量。我不确定上述示例是否适用于上述情况。如果是这样,我不知道如何。

上面的代码怎么会变成 undesired/unexpected 行为?

Do all getters that return a variable potentially modified by a different thread be protected with mutex or equivalent?

是的。如果多个线程访问同一个 non-atomic 对象并且这些访问中至少有一个是写入,那么 所有 访问必须同步,而不仅仅是写入,否则会有一个数据竞赛。包含数据争用的程序具有未定义的行为。

However, I can't imagine the case in which the above code may cause a problem.

您想将程序的可靠性押在您想象力的广度上吗?当你已经知道什么是正确的事情时,为什么还要花精力思考你可能能够逃脱的事情呢?特别是,未定义的行为是 undefined——您不必限制其表现的范围。

How can the code above end up in undesired/unexpected behavior?

很容易。

考虑一下:

void busy_wait() {
    while (mod_get_var()) ;
}

现在假设编译器将 mod_get_var() 调用内联为直接读取 var。该读取不同步,因此编译器没有义务考虑不同读取将观察到不同值的可能性。因此,它可能会将函数优化为等同于

void busy_wait() {
    if (var) while(1) ;
}

如果您指望用不同的线程来指示线程脱离 busy_wait(),那么您可能会大吃一惊。