我最近用以下骨架编写了一个代码:
variable;
callback(){
//variable updated here
}
thread_function(){
//variable used
}
main(){
//callback registered
//thread registered
}
我发现只要在回调时更新variable
,它就会在线程中自动更新,而不会将variable
声明为volatile。好吧,我不清楚它是如何管理的。先感谢您。之间,从使用代码编译的库中调用callback()。
答案 0 :(得分:6)
好的,首先,它被打破了。你很幸运,你的编译器创建的代码偶然会起作用(或者说运气不好,因为它可以隐藏极端情况下的细微错误)。
我发现只要变量在回调时更新,它就会在线程中自动更新,而不会将变量声明为volatile。好吧,我不清楚它是如何管理的。
从这里开始:它是同一个变量。线程共享相同的地址空间。所以,这就是你天真的期望。
volatile
是关于优化的。 C编译器可以自由地对代码进行大量修改,以使其更快,这包括重新排序语句,而不是读取访问变量,因为相同的值在寄存器中,甚至"展开"循环等等。通常情况下,唯一的限制是可观察行为保持不变(google for it,我不想在这里写一本书。)
从普通内存中读取变量不会产生任何副作用,因此可以在不改变行为的情况下合法地删除它。 C(c11之前)不了解线程。如果未在代码的某些部分写入变量,则假定它保持与以前相同的值。
现在,volatile
给你的是告诉编译器这不是正常的内存,而是一个可能在你的程序控制范围之外改变的位置(比如一个内存映射的I / O寄存器)。对于volatile
,编译器必须实际获取任何读操作的变量,并实际存储它以用于任何写操作。它也不允许重新排序多个volatile
变量之间的访问。但全部并且不够用于同步线程。为此,您还需要保证在变量访问时不会重新排序其他内存访问或代码执行,即使使用多处理器 - >你需要一个内存障碍。
注意这与例如不同。 java其中volatile
为您提供了线程同步所需的内容。在c中,使用pthreads
库为您提供的内容:互斥,信号量和条件变量。
您的代码无意中正常运行 。在c中,volatile
表示线程错误(且不必要),请使用pthreads
提供的同步原语。