C 静态线程标志和-O3

C 静态线程标志和-O3,c,multithreading,C,Multithreading,我试着编写一个单一生产者-消费者实现。 我在使用优化进行编译时遇到了一个问题。 在gcc中使用优化(-O3)运行时,线程被卡住 添加volatile或从全局标志中删除static时,线程按预期工作。 为什么会这样 #include <stdio.h> #include <pthread.h> static volatile int flag = 0; /* this is the line */ static int resource = 0; void *Write

我试着编写一个单一生产者-消费者实现。 我在使用优化进行编译时遇到了一个问题。 在gcc中使用优化(-O3)运行时,线程被卡住

添加volatile或从全局标志中删除static时,线程按预期工作。 为什么会这样

#include <stdio.h>
#include <pthread.h>

static volatile int flag = 0; /* this is the line */
static int resource = 0;

void *Writer(void *somthing);
void *Reader(void *somthing);

int main()
{
    pthread_t id1 = 0;
    pthread_t id2 = 0;

    pthread_create(&id1, NULL, Writer, NULL);
    pthread_create(&id2, NULL, Reader, NULL);

    return 0;
}

void *Writer(void *somthing)
{
    while(1)
    {
        while (1 == flag);
        ++resource;
        flag = 1;
    }

    return NULL;
}

void *Reader(void *somthing)
{
    while(1)
    {
        while(0 == flag);
        fprintf(stderr,"%d\n",resource);
        flag = 0;
    }

    return NULL;
}```
#包括
#包括
静态易失性int标志=0;/*这是电话线*/
静态int资源=0;
void*Writer(void*somthing);
void*Reader(void*somthing);
int main()
{
pthread_t id1=0;
pthread_t id2=0;
pthread_create(&id1,NULL,Writer,NULL);
pthread_create(&id2,NULL,Reader,NULL);
返回0;
}
void*Writer(void*somthing)
{
而(1)
{
而(1==标志);
++资源;
flag=1;
}
返回NULL;
}
void*Reader(void*somthing)
{
而(1)
{
而(0==标志);
fprintf(stderr,“%d\n”,资源);
flag=0;
}
返回NULL;
}```

如果您正在编写编译器,并且发现

while(flag == 1)
   ;
你会怎么做?我会优化它,因为
flag
不可能在循环内改变


但是,在某些情况下,其他一些东西可能会在您不知道的情况下更改
flag
。这就是
volatile
的作用:它告诉编译器预期未执行的对象。

volatile
向编译器显示对象“容易产生副作用”,这意味着它可以被不在正常程序执行路径上的某个对象更改

voaltile
对象每次使用时都会从其内存位置读取。程序将在每次修改时更新其内存存储

这里很容易看出区别。

哪个gcc版本和目标?我认为gcc会意识到文件范围变量可能会因线程回调而改变。难道不是这样吗?这个bug是一个非常古老的现象,现在的PC编译器应该已经意识到了。你不能只使用volatile编写线程安全的代码。记忆障碍是一项极其严格的要求。不要自己写,借或偷。喜欢