c - 在多线程环境中遵循指针

标签 c multithreading pthreads c99 compiler-optimization

如果我有一些看起来像这样的代码:

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/

相关文章:

c - 奇怪的 C 程序行为

c - pthread_detach 不会改变任何东西

c - pthread 唤醒执行

c++ - 在循环中使用 dup2() 和 create() 在 Linux 中重定向

c++ - c++中的指针和引用的概念和c中的一样吗?

c - GLib - class_init 和 init 类方法之间的区别

c++ - 并行计算大 vector 的总和

java - 线程进度条 fragment

c - 使用 C 中的结构将数据存储到动态数组中

c# - 系统正常运行时间和 MemoryBarrier