Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
简单的C程序来说明无序执行?_C_Multithreading_X86_Memory Barriers - Fatal编程技术网

简单的C程序来说明无序执行?

简单的C程序来说明无序执行?,c,multithreading,x86,memory-barriers,C,Multithreading,X86,Memory Barriers,我正在运行x86,我想实际看到一个错误,它是由我的机器上的无序执行引起的。我试着写了一篇,但我总是看到“x的值是33”: #包括 #包括 #包括 int x,f; void*handler(void*ptr){ 而(f==0); //期望值:有时,由于exec出现故障,应该打印11 printf(“x的值为%d\n”,x); 返回NULL; } int main(){ pthread_t thread1; 而(1){ x=11;f=0; pthread_create(&thread1,NULL,

我正在运行x86,我想实际看到一个错误,它是由我的机器上的无序执行引起的。我试着写了一篇,但我总是看到“x的值是33”:

#包括
#包括
#包括
int x,f;
void*handler(void*ptr){
而(f==0);
//期望值:有时,由于exec出现故障,应该打印11
printf(“x的值为%d\n”,x);
返回NULL;
}
int main(){
pthread_t thread1;
而(1){
x=11;f=0;
pthread_create(&thread1,NULL,handler,NULL);
x=33;
f=1;
pthread_join(thread1,NULL);
}   
返回0;
}

什么是最简单的c程序,可以说明一个无序的执行错误?为什么有时不打印“x的值为11”

您试图创建的效果并不依赖于无序执行。这只是可以创建内存重新排序的因素之一。此外,现代x86执行时会出现无序,但它使用内存顺序缓冲区来确保提交到L1d/的存储以程序顺序全局可见。(因为x86的内存模型只允许StoreLoad重新排序,而不允许StoreStore。)

内存重新排序与指令执行重新排序是分开的,因为即使按顺序CPU也使用存储缓冲区来避免缓存未命中存储暂停


如果
x
f
在不同的缓存线中结束,则顺序ARM CPU上的C实现可以打印11或33。


我假设您在编译时禁用了优化功能,因此编译器会有效地处理所有变量
volatile
,即
volatile int x,f
。否则,
while(f==0)
,则代码>循环将编译为
,只检查
f
一次。(非原子变量的数据竞争允许编译器从循环中提升负载,但
volatile
负载必须始终完成。)

生成的asm/机器代码中的存储将以C源代码顺序显示

您是为x86编译的,它有一个强大的内存模型:x86存储是发布存储,x86加载是获取加载。您不能获得顺序一致性,但可以免费获得acq_rel。(对于未优化的代码,即使您不要求,也会发生这种情况。)

因此,在没有针对x86进行优化的情况下编译时,您的程序相当于

_Atomic int x, f;

int main(){
    ...
    pthread_create
    atomic_store_explicit(&x, 33, memory_order_release);
    atomic_store_explicit(&f, 1, memory_order_release);
    ...
}
负载侧也是如此。
while(f==0){}
是x86上的一个获取负载,因此让读取端等待直到它看到非零的
f
可以保证它也看到
x==33

但是,如果您为弱顺序的ISA(如ARM或PowerPC)编译,asm级别的内存排序保证确实允许StoreStore和LoadLoad重新排序,因此,如果编译时未进行优化,您的程序可能会打印
11


另请参见

线程启动不够快。只需在主函数中创建一个
sleep()
即可获得您的11值。另一种方法是(可能)在系统中加载一些CPU密集型进程,以更改取消竞争condition@Jean-Françoisfab但是
handler
f=1之前什么都不做已完成,此时
x=33已经完成。@Jean-Françoisfare不认为这里有比赛条件。@kiranBiradar在(f==0)退出
之后约束,如果您多次运行程序,时间片调度将分离
pthread\u create(&thread1,NULL,handler,NULL)
x=33
并在裂缝中运行
处理程序
,以报告
11
_Atomic int x, f;

int main(){
    ...
    pthread_create
    atomic_store_explicit(&x, 33, memory_order_release);
    atomic_store_explicit(&f, 1, memory_order_release);
    ...
}