c – 在多线程环境中跟随指针

前端之家收集整理的这篇文章主要介绍了c – 在多线程环境中跟随指针前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如果我有一些看起来像这样的代码
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);
}

解决方法

通常,您应该在等待条件对象之前尝试锁定pthread互斥锁,因为pthread_cond_wait调用释放互斥锁(并在返回之前重新获取它).所以,你的check_flag函数应该被重写,以符合pthread条件下的语义.
void check_flag(foo_t* f) {
    pthread_mutex_lock(&f->m);
    while(f->flag)
        pthread_cond_wait(&f->c,&f->m);
    pthread_mutex_unlock(&f->m);
}

关于是否允许编译器优化标志字段的读取的问题,这个answer比我更详细地解释了它.

基本上,编译器知道pthread_cond_wait,pthread_mutex_lock和pthread_mutex_unlock的语义.他知道在这种情况下他无法优化内存读取(在这个例子中调用pthread_cond_wait).这里没有记忆障碍的概念,只是对某些功能的特殊知识,以及在他们面前遵循的一些规则.

还有一件事可以保护您免受处理器执行的优化.您的平均处理器能够重新排序内存访问(读/写),前提是语义是守恒的,并且它总是这样做(因为它允许提高性能).但是,当多个处理器可以访问相同的内存地址时,这会中断.内存屏障只是处理器的指令,告诉它可以移动在屏障之前发出的读/写并在屏障之后执行它们.它现在已经完成了.

猜你在找的C&C++相关文章