代码在没有 volatile 的情况下工作正常?
code working fine without volatile?
嗨,我最近用以下框架写了一个代码:
variable;
callback(){
//variable updated here
}
thread_function(){
//variable used
}
main(){
//callback registered
//thread registered
}
我发现每当 variable
在回调中更新时,它会在线程中自动更新,而无需将 variable
声明为易失性。好吧,我不清楚它是如何管理的。先感谢您。两者之间,从使用代码编译的库中调用 callback()。
好的,首先,它坏了。你很幸运,你的编译器创建的代码,偶然地,似乎可以工作(或者可能是不幸的,因为它可能隐藏角落案例中的细微错误)。
I found that whenever the variable is updated at callback, its automatically updated in the thread without declaring the variable as a volatile. well, I am not clear how it is managed.
从这里开始:这是同一个变量。线程共享相同的地址 space。所以,这就是你天真的期望。
volatile
是关于优化的。 C 编译器可以自由地对您的代码进行大量修改以使其更快,这包括重新排序语句,而不是读取访问的变量,因为相同的值在寄存器中,甚至 "unrolling" 循环等等更多的。通常,唯一的限制是可观察行为保持不变(google,我不想在这里写书。)
从普通内存中读取变量不会产生任何副作用,因此可以在不改变行为的情况下合法地忽略它。 C(在 c11 之前)不知道线程。如果在代码的某些部分没有写入变量,则假定它与以前保持相同的值。
现在,volatile
告诉编译器这不是普通内存,而是一个可以在程序控制之外更改的位置(例如内存映射 I/O 寄存器) .使用 volatile
,编译器必须为任何读取操作实际获取变量,并为任何写入操作实际存储它。也不允许对几个 volatile
变量之间的访问重新排序。但是仅此而已并且还不够同步线程。为此,您还需要保证没有其他内存访问或代码执行围绕您的变量访问重新排序,即使使用多处理器也是如此 -> 您需要一个 内存屏障 .
请注意,这与例如java where volatile
gives you what you need for thread synchronization. In c,使用 pthreads
库为您提供的内容:互斥锁、信号量 和条件变量.
tl;博士
您的代码可以正常工作意外。在 c 中,线程的 volatile
是错误的(并且不必要),使用 pthreads
提供的同步原语。
嗨,我最近用以下框架写了一个代码:
variable;
callback(){
//variable updated here
}
thread_function(){
//variable used
}
main(){
//callback registered
//thread registered
}
我发现每当 variable
在回调中更新时,它会在线程中自动更新,而无需将 variable
声明为易失性。好吧,我不清楚它是如何管理的。先感谢您。两者之间,从使用代码编译的库中调用 callback()。
好的,首先,它坏了。你很幸运,你的编译器创建的代码,偶然地,似乎可以工作(或者可能是不幸的,因为它可能隐藏角落案例中的细微错误)。
I found that whenever the variable is updated at callback, its automatically updated in the thread without declaring the variable as a volatile. well, I am not clear how it is managed.
从这里开始:这是同一个变量。线程共享相同的地址 space。所以,这就是你天真的期望。
volatile
是关于优化的。 C 编译器可以自由地对您的代码进行大量修改以使其更快,这包括重新排序语句,而不是读取访问的变量,因为相同的值在寄存器中,甚至 "unrolling" 循环等等更多的。通常,唯一的限制是可观察行为保持不变(google,我不想在这里写书。)
从普通内存中读取变量不会产生任何副作用,因此可以在不改变行为的情况下合法地忽略它。 C(在 c11 之前)不知道线程。如果在代码的某些部分没有写入变量,则假定它与以前保持相同的值。
现在,volatile
告诉编译器这不是普通内存,而是一个可以在程序控制之外更改的位置(例如内存映射 I/O 寄存器) .使用 volatile
,编译器必须为任何读取操作实际获取变量,并为任何写入操作实际存储它。也不允许对几个 volatile
变量之间的访问重新排序。但是仅此而已并且还不够同步线程。为此,您还需要保证没有其他内存访问或代码执行围绕您的变量访问重新排序,即使使用多处理器也是如此 -> 您需要一个 内存屏障 .
请注意,这与例如java where volatile
gives you what you need for thread synchronization. In c,使用 pthreads
库为您提供的内容:互斥锁、信号量 和条件变量.
tl;博士
您的代码可以正常工作意外。在 c 中,线程的 volatile
是错误的(并且不必要),使用 pthreads
提供的同步原语。