所有 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()
,那么您可能会大吃一惊。
让我们假设以下 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()
,那么您可能会大吃一惊。