如果我有一些看起来像这样的代码:
typedef struct {
bool some_flag;
pthread_cond_t c;
pthread_mutex_t m;
} foo_t;
// I assume the mutex has already been locked, and will be unlocked
// some time after this function returns. For clarity. Definitely not
// out of laziness ;)
void check_flag(foo_t* f) {
while(f->flag)
pthread_cond_wait(&f->c, &f->m);
}
C 标准中是否有任何内容阻止优化器将 check_flag 重写为:
void check_flag(foo_t* f) {
bool cache = f->flag;
while(cache)
pthread_cond_wait(&f->c, &f->m);
}
换句话说,生成的代码是否必须每次循环都遵循f
指针,或者编译器是否可以自由地取消引用?
如果可以随意拔出来,有什么办法可以防止吗?我需要在某处添加一个 volatile 关键字吗?它不能是 check_flag
的参数,因为我计划在此结构中包含其他变量,我不介意编译器像这样优化。
我可能不得不求助于:
void check_flag(foo_t* f) {
volatile bool* cache = &f->some_flag;
while(*cache)
pthread_cond_wait(&f->c, &f->m);
}
最佳答案
在一般情况下,即使不涉及多线程并且您的循环看起来像:
void check_flag(foo_t* f) {
while(f->flag)
foo(&f->c, &f->m);
}
编译器将无法缓存 f->flag
测试。这是因为编译器无法知道函数(如上面的 foo()
)是否会更改 f
指向的任何对象。
在特殊情况下(foo()
对编译器可见,并且已知所有传递给 check_flag()
的指针都不会被别名或以其他方式修改 foo()
) 编译器可能能够优化检查。
但是,pthread_cond_wait()
的实现方式必须能够阻止该优化。
参见 Does guarding a variable with a pthread mutex guarantee it's also not cached? :
您可能还对 Steve Jessop 的回答感兴趣:Can a C/C++ compiler legally cache a variable in a register across a pthread library call?
但是,您想在自己的工作中将 Boehm 的论文提出的问题解决到什么程度取决于您。据我所知,如果您想认为 pthreads 没有/不能做出保证,那么您实际上是在认为 pthreads 是无用的(或者至少不提供安全保证,这我认为减少具有相同的结果)。虽然这在最严格的意义上可能是正确的(如论文中所述),但它也可能不是一个有用的答案。除了基于 Unix 的平台上的 pthreads,我不确定你还有什么选择。
关于c - 在多线程环境中遵循指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4686672/