由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
Programming版 - 用volatile退出线程对不对?(C++)
相关主题
Bihai,你就用atmoic完事了线程共享变量问题,搞不懂。
Volatile variables do not provide any atomicity (转载)How to use volatile in c++?
关于线程读写全局变量的问题java的同步问题请教
问个C++编译器如何处理函数内的static 变量Concurrency of assignment statement in C
C++ InitializeCriticalSection问题关于signal handler
说到cpp11 和 围棋的对比问达人一个shared memory 的问题
请教一个c语言实现多线程的问题用STL map的时候怎么自己定义大小比较的关系
question about volatile variable on multiple coresC++ template question
相关话题的讨论汇总
话题: volatile话题: c++话题: 线程话题: barrier话题: quit
进入Programming版参与讨论
1 (共1页)
b***i
发帖数: 3043
1
网上很多说volatile和线程就没有关系。
我现在计划在线程里面
volatile bool quit=false;
void worker(){
while(!quit){
...
}
}
然后在一个UI的按钮那里
quit=true;
这样对不对?
d***a
发帖数: 13752
2
这样做没问题,应该这样做。
p***o
发帖数: 1252
3
volatile确实和线程没关系,不过C++11之前编译器约定俗成这么干也行。
C++11以后还是用std::atomic那一堆把。

【在 b***i 的大作中提到】
: 网上很多说volatile和线程就没有关系。
: 我现在计划在线程里面
: volatile bool quit=false;
: void worker(){
: while(!quit){
: ...
: }
: }
: 然后在一个UI的按钮那里
: quit=true;

c*********e
发帖数: 16335
4
volatile本来就和线程没關係。

【在 b***i 的大作中提到】
: 网上很多说volatile和线程就没有关系。
: 我现在计划在线程里面
: volatile bool quit=false;
: void worker(){
: while(!quit){
: ...
: }
: }
: 然后在一个UI的按钮那里
: quit=true;

d***a
发帖数: 13752
5
std::atomic在运行时间上的开销比volatile要大一点。
不过既然已经用了C++了,这点额外开销倒也不算什么。

【在 p***o 的大作中提到】
: volatile确实和线程没关系,不过C++11之前编译器约定俗成这么干也行。
: C++11以后还是用std::atomic那一堆把。

b***i
发帖数: 3043
6
atomic_flag?
会不会没有什么额外的开销(比 volatile?)

【在 d***a 的大作中提到】
: std::atomic在运行时间上的开销比volatile要大一点。
: 不过既然已经用了C++了,这点额外开销倒也不算什么。

b***i
发帖数: 3043
7
就是说之后,约定俗称这么干不成了?我靠

【在 p***o 的大作中提到】
: volatile确实和线程没关系,不过C++11之前编译器约定俗成这么干也行。
: C++11以后还是用std::atomic那一堆把。

p***o
发帖数: 1252
8
你要讨论开销,首先要确认没有false sharing,然后去研究下memory_order_seq_cst
和memory_order_release/acquire的区别。至于volatile这种都不在标准里的东西,
除非你的gcc太老(<4.7之类),没啥讨论的必要。SO上有篇文章 Why is std::atomic<
bool> much slower than volatile bool? 你可以参考一下。

【在 b***i 的大作中提到】
: atomic_flag?
: 会不会没有什么额外的开销(比 volatile?)

w***g
发帖数: 5958
9
volatile的本意应该不是为了搞多线程,
而是为了应对硬件自动改变变量的值的情况,
是dos时代的东西。有了保护模式后volatile
似乎就没用了。
也可能是我记错了。

【在 b***i 的大作中提到】
: 网上很多说volatile和线程就没有关系。
: 我现在计划在线程里面
: volatile bool quit=false;
: void worker(){
: while(!quit){
: ...
: }
: }
: 然后在一个UI的按钮那里
: quit=true;

s********k
发帖数: 6180
10
不只是硬件改,也可能是防止编译器去优化code把几个用于做些奇怪时序逻辑的code编
译掉

【在 w***g 的大作中提到】
: volatile的本意应该不是为了搞多线程,
: 而是为了应对硬件自动改变变量的值的情况,
: 是dos时代的东西。有了保护模式后volatile
: 似乎就没用了。
: 也可能是我记错了。

相关主题
说到cpp11 和 围棋的对比线程共享变量问题,搞不懂。
请教一个c语言实现多线程的问题How to use volatile in c++?
question about volatile variable on multiple coresjava的同步问题请教
进入Programming版参与讨论
c*********e
发帖数: 16335
11
compiler有时候会把几行代码的次序颠倒,很闹心。

【在 w***g 的大作中提到】
: volatile的本意应该不是为了搞多线程,
: 而是为了应对硬件自动改变变量的值的情况,
: 是dos时代的东西。有了保护模式后volatile
: 似乎就没用了。
: 也可能是我记错了。

d***a
发帖数: 13752
12
volatile和dos没关系啊。它的目的是告䜣编辑器,硬件或其它代码可能会改变
此变量,所以编辑器产生机器代码时,要保证每次对此变量的读写,都是针对其在内存
中的内容,而不是其在寄存器中内容。这个用法在OS代码,I/O驱动程序或嵌入式编程
中很常见。

【在 w***g 的大作中提到】
: volatile的本意应该不是为了搞多线程,
: 而是为了应对硬件自动改变变量的值的情况,
: 是dos时代的东西。有了保护模式后volatile
: 似乎就没用了。
: 也可能是我记错了。

b***i
发帖数: 3043
13
即使编译器不搞,CPU也会搞。
但是这里的代码只有一行,在UI按钮那里把bool值改了,没有乱序执行的问题。而bool
怎么着都不需要考虑是不是原子操作吧?它只要不是0我就满意啦,所以也没有原子操
作的需要。
那么,在这里用volatile到底能不能解决问题?比如我有多个CPU?

【在 c*********e 的大作中提到】
: compiler有时候会把几行代码的次序颠倒,很闹心。
c*********e
发帖数: 16335
14
看着还行。
不過,建议你用google搜一下,c++, java, c#处理multi-threading的代码不一样的。

bool

【在 b***i 的大作中提到】
: 即使编译器不搞,CPU也会搞。
: 但是这里的代码只有一行,在UI按钮那里把bool值改了,没有乱序执行的问题。而bool
: 怎么着都不需要考虑是不是原子操作吧?它只要不是0我就满意啦,所以也没有原子操
: 作的需要。
: 那么,在这里用volatile到底能不能解决问题?比如我有多个CPU?

d***a
发帖数: 13752
15
没有问题。worker()和UI代码在一个CPU上或不同CPU上运行都可以,如果后者是
hardware shared memory的机器。
你的代码其实很简单,一个writer一个reader,只有一个共享变量。atomic是用来解决
更复杂的情况的。

bool

【在 b***i 的大作中提到】
: 即使编译器不搞,CPU也会搞。
: 但是这里的代码只有一行,在UI按钮那里把bool值改了,没有乱序执行的问题。而bool
: 怎么着都不需要考虑是不是原子操作吧?它只要不是0我就满意啦,所以也没有原子操
: 作的需要。
: 那么,在这里用volatile到底能不能解决问题?比如我有多个CPU?

h**********c
发帖数: 4120
16
不是不对,是对同步得理解,同步没有semaphore或其他synchronization 机制会
starvation
说到这里,你对slicing得理解是怎样的,在什么样的情况下,你认为你应该研究一下
slicing?
d***a
发帖数: 13752
17
话说回来,这个代码结构虽然从运行上说是正确的,但它是典型的busy waiting,CPU
空转等待,效率很低。一般用在没有操作系统的机器上,或者是高性能并行计算,每个
thread独占一个CPU核的情况。

bool

【在 d***a 的大作中提到】
: 没有问题。worker()和UI代码在一个CPU上或不同CPU上运行都可以,如果后者是
: hardware shared memory的机器。
: 你的代码其实很简单,一个writer一个reader,只有一个共享变量。atomic是用来解决
: 更复杂的情况的。
:
: bool

b***i
发帖数: 3043
18
好像确实不对了,说的是某些CPU比如Alpha, ARM,和x86是不一样的,volatile自己不
能保证任何事情。完全取决于编译器是否还是按照原来的约定俗成的方案
新的方法是用C++的标准写法,有各种不同级别。
另外,退出线程除了busy wait,好像没有别的办法。即使OS能够在context switch的
时候查询是否要退出线程,但是没法正确的释放所有的资源,因为代码并没有执行完。
所以还得代码自己解决这个问题。

【在 d***a 的大作中提到】
: 没有问题。worker()和UI代码在一个CPU上或不同CPU上运行都可以,如果后者是
: hardware shared memory的机器。
: 你的代码其实很简单,一个writer一个reader,只有一个共享变量。atomic是用来解决
: 更复杂的情况的。
:
: bool

d***a
发帖数: 13752
19
有这种事?这几个CPU我全用过啊。:) 从机器层面来说,volatile的意思很简单,就是
要程序每次读写变量时都要访问内存,不要只对cpu register操作。
我觉得你的代码在这里可能有潜在问题:
while(!quit){
...
}
我记得在UI代码里,常见的写法是
while(!quit) {
sigwait(...); // or something similar, depending on the system
}
... // the work to do, e.g. quit the process
这样做的原因是,假设button代码不是在某种抢占方式下运行,那while(!quit)会把整
个程序阻塞住,button代码就没有机会被执行了,quit的值也就一直是false了。

【在 b***i 的大作中提到】
: 好像确实不对了,说的是某些CPU比如Alpha, ARM,和x86是不一样的,volatile自己不
: 能保证任何事情。完全取决于编译器是否还是按照原来的约定俗成的方案
: 新的方法是用C++的标准写法,有各种不同级别。
: 另外,退出线程除了busy wait,好像没有别的办法。即使OS能够在context switch的
: 时候查询是否要退出线程,但是没法正确的释放所有的资源,因为代码并没有执行完。
: 所以还得代码自己解决这个问题。

M********t
发帖数: 5032
20
你这个关于volatile的说法是对的,volatile is just a hint to compiler。
另外,busy wait一般不是个好idea。可以考虑其他primitive。例如semaphore唤醒干
活,干完检查flag。

【在 b***i 的大作中提到】
: 好像确实不对了,说的是某些CPU比如Alpha, ARM,和x86是不一样的,volatile自己不
: 能保证任何事情。完全取决于编译器是否还是按照原来的约定俗成的方案
: 新的方法是用C++的标准写法,有各种不同级别。
: 另外,退出线程除了busy wait,好像没有别的办法。即使OS能够在context switch的
: 时候查询是否要退出线程,但是没法正确的释放所有的资源,因为代码并没有执行完。
: 所以还得代码自己解决这个问题。

相关主题
Concurrency of assignment statement in C用STL map的时候怎么自己定义大小比较的关系
关于signal handlerC++ template question
问达人一个shared memory 的问题how to write some C/C++ program to enable dual monitor?
进入Programming版参与讨论
M********t
发帖数: 5032
21
这些指令是编译器产生的,机器本身并不认识volatile。编译器可能想:这个值肯定是
这个呀,不用读memory呀,于是就优化掉了。volatile强迫编译器产生相应代码。

【在 d***a 的大作中提到】
: 有这种事?这几个CPU我全用过啊。:) 从机器层面来说,volatile的意思很简单,就是
: 要程序每次读写变量时都要访问内存,不要只对cpu register操作。
: 我觉得你的代码在这里可能有潜在问题:
: while(!quit){
: ...
: }
: 我记得在UI代码里,常见的写法是
: while(!quit) {
: sigwait(...); // or something similar, depending on the system
: }

d***a
发帖数: 13752
22
那是自然,机器只认机器指令。

【在 M********t 的大作中提到】
: 这些指令是编译器产生的,机器本身并不认识volatile。编译器可能想:这个值肯定是
: 这个呀,不用读memory呀,于是就优化掉了。volatile强迫编译器产生相应代码。

b***i
发帖数: 3043
23
问题是我的活是无穷的,不是短时间完成的。
例子,游戏刷新一个帧,那么一秒钟需要检查这个变量几十次。
我在做一个解释器(字节码)就是不停地进行解释。那么要停止,只有在每个解释开始
前检测是否需要退出解释线程。这样主程序可以有个按钮,可以停止正在进行的解释执
行。

【在 M********t 的大作中提到】
: 你这个关于volatile的说法是对的,volatile is just a hint to compiler。
: 另外,busy wait一般不是个好idea。可以考虑其他primitive。例如semaphore唤醒干
: 活,干完检查flag。

c*********e
发帖数: 16335
24
对,如果只有一个cpu,还是别老是想multi-threading.

CPU

【在 d***a 的大作中提到】
: 话说回来,这个代码结构虽然从运行上说是正确的,但它是典型的busy waiting,CPU
: 空转等待,效率很低。一般用在没有操作系统的机器上,或者是高性能并行计算,每个
: thread独占一个CPU核的情况。
:
: bool

b***i
发帖数: 3043
25
一个也可以啊,所以叫抢占式,99年windows就可以了。一个线程可以光画图,仍然看
到鼠标键盘可以及时响应。线程可以定义优先度,定义最不优先就行。

【在 c*********e 的大作中提到】
: 对,如果只有一个cpu,还是别老是想multi-threading.
:
: CPU

d***a
发帖数: 13752
26
你可能得说说操作系统是什么,用的什么线程和UI中间层,这样大伙才好有的放矢。
如果是没有操作系统的运行环境,一般是把quit = false放在interrupt handler里。
然后quit声明成volatile,就象你写的那样,是标准做法。

【在 b***i 的大作中提到】
: 一个也可以啊,所以叫抢占式,99年windows就可以了。一个线程可以光画图,仍然看
: 到鼠标键盘可以及时响应。线程可以定义优先度,定义最不优先就行。

b***i
发帖数: 3043
27
希望是跨平台的,所以用C++11吧。那,线程就是C++11的线程,thread/async那些吧。
至于系统,Windows, Linux吧。

【在 d***a 的大作中提到】
: 你可能得说说操作系统是什么,用的什么线程和UI中间层,这样大伙才好有的放矢。
: 如果是没有操作系统的运行环境,一般是把quit = false放在interrupt handler里。
: 然后quit声明成volatile,就象你写的那样,是标准做法。

F****n
发帖数: 3271
28
Don't use volatile. Your code is NOT guaranteed to be correct on all
platforms. Unlike in Java, volatile keyword in C++ does NOT enforce memory
barrier, and as a result, the code in your "while(!quit)" loop may be
reordered at the will of the compiler and/or the runtime system.
A rule of thumb in C/C++ is NEVER use volatile.

【在 b***i 的大作中提到】
: 网上很多说volatile和线程就没有关系。
: 我现在计划在线程里面
: volatile bool quit=false;
: void worker(){
: while(!quit){
: ...
: }
: }
: 然后在一个UI的按钮那里
: quit=true;

c*********e
发帖数: 16335
29
java里也不推荐用volatile.

【在 F****n 的大作中提到】
: Don't use volatile. Your code is NOT guaranteed to be correct on all
: platforms. Unlike in Java, volatile keyword in C++ does NOT enforce memory
: barrier, and as a result, the code in your "while(!quit)" loop may be
: reordered at the will of the compiler and/or the runtime system.
: A rule of thumb in C/C++ is NEVER use volatile.

w**z
发帖数: 8232
30
是你不推荐吧

:java里也不推荐用volatile.
相关主题
请教: 用stable_sort 在VC++下通过但在g++下通不过Volatile variables do not provide any atomicity (转载)
one more c++ question关于线程读写全局变量的问题
Bihai,你就用atmoic完事了问个C++编译器如何处理函数内的static 变量
进入Programming版参与讨论
S*A
发帖数: 7142
31
这个理解似乎不是很对。
volatile 就是告诉 CPU 不要优化这个变量 Load/Store 的操作。
每个 memory load/store 都不能省,是有很明确的结果的。
load/store 的优化一般有:
同一个地方load 多次,中间没有写,后面的load和前面一样。
有多个store,前面的 store 可以去掉,最后一个 store 赢。
volatile 保证没有一个 load/store 被省略了。
其他派生出来的就是如何根据这个原理用而以。

【在 b***i 的大作中提到】
: 好像确实不对了,说的是某些CPU比如Alpha, ARM,和x86是不一样的,volatile自己不
: 能保证任何事情。完全取决于编译器是否还是按照原来的约定俗成的方案
: 新的方法是用C++的标准写法,有各种不同级别。
: 另外,退出线程除了busy wait,好像没有别的办法。即使OS能够在context switch的
: 时候查询是否要退出线程,但是没法正确的释放所有的资源,因为代码并没有执行完。
: 所以还得代码自己解决这个问题。

c*********e
发帖数: 16335
32
java里用volatile,最好只用在bool上。现在有AtomicBoolean了,就不必要用
volatile bool了。
java里推荐用immutable.

【在 w**z 的大作中提到】
: 是你不推荐吧
:
: :java里也不推荐用volatile.
: :

h**********c
发帖数: 4120
33
当初记得是理解为volatile 是不会保留 thread local value,讲操作系统锁说过是两
boolean,说明设计者对可靠性的理解。
其实以前记得讨论过,用一个循环主要是处理missing signal,这个很讨厌,就是很贵
的solaris可能也不能保证notify.所以多线程,和多进程一样,也不一样,因为进程有
返回值,返回了就结束了,也可以wait, wait抓住信号,就可定结束了。但这两条对多
线程不适用。
这都是在实际中写出来的。但多线程的目的是什么呢,主要的目的比如,一个线程处理
一个socket,这样单个线程可以保证收发不影响别的socket。
这些东西也很依赖硬件实现。好在现在基本也都是X86-64.
总之,这个地方,你要问while loop 是对的,是为了处理missing signal, volatile
不volatile应该理解告诉每个thread 不要保留local copy,而是直接取共享值的地址,
也是告诉读程序的人,这个值是要共享的。
最后要理解的是,你永远无法判定一个线程或进程是否在运行,你只能知道它已经结束
了。所以volatile不volatile并不重要,但volatile更好些。
F****n
发帖数: 3271
34
This is one of the most common misconceptions in C/C++ which have led to
numerous bugs in practice.
The fact is that in C/C++, volatile only tells the compiler "do not optimize
away" this variable. It says NOTHING about load/store operations.
Taking LZ's original post as an example, using volatile will only guarantee
his code will work in a single thread situation, but not in a multi-thread
situation.
You may wonder how could LZ's example be in a single-thread situation. You
are right - this is the reason the keyword volatile is almost useless. But
in rare cases, it is possible when the volatile variable is for hardware
access. That's the only valid use case for volatile in C/C++.

【在 S*A 的大作中提到】
: 这个理解似乎不是很对。
: volatile 就是告诉 CPU 不要优化这个变量 Load/Store 的操作。
: 每个 memory load/store 都不能省,是有很明确的结果的。
: load/store 的优化一般有:
: 同一个地方load 多次,中间没有写,后面的load和前面一样。
: 有多个store,前面的 store 可以去掉,最后一个 store 赢。
: volatile 保证没有一个 load/store 被省略了。
: 其他派生出来的就是如何根据这个原理用而以。

F****n
发帖数: 3271
35
That's not correct. Java volatile is fine. It is equivalent to atomic
without compare.
I don't buy this immutable thing. Like design patterns, it is over-promoted
by biblical theorists with little practical experience, and it normally adds
a lot of unnecessary crap to a simple problem.

【在 c*********e 的大作中提到】
: java里用volatile,最好只用在bool上。现在有AtomicBoolean了,就不必要用
: volatile bool了。
: java里推荐用immutable.

d***a
发帖数: 13752
36
草虫的理解是正确的。从体系结构和代码生成的角度来看,volatile是一个很简单的概
念。在语言层做大多的解读,反而把概念搞复杂了。

【在 S*A 的大作中提到】
: 这个理解似乎不是很对。
: volatile 就是告诉 CPU 不要优化这个变量 Load/Store 的操作。
: 每个 memory load/store 都不能省,是有很明确的结果的。
: load/store 的优化一般有:
: 同一个地方load 多次,中间没有写,后面的load和前面一样。
: 有多个store,前面的 store 可以去掉,最后一个 store 赢。
: volatile 保证没有一个 load/store 被省略了。
: 其他派生出来的就是如何根据这个原理用而以。

F****n
发帖数: 3271
37
How many times do I need to repeat:
This is NOT correct in C/C++.

【在 d***a 的大作中提到】
: 草虫的理解是正确的。从体系结构和代码生成的角度来看,volatile是一个很简单的概
: 念。在语言层做大多的解读,反而把概念搞复杂了。

d***a
发帖数: 13752
38
You are wrong.

【在 F****n 的大作中提到】
: How many times do I need to repeat:
: This is NOT correct in C/C++.

F****n
发帖数: 3271
39
https://en.wikipedia.org/wiki/Volatile_(computer_programming)
Quotes:
"Operations on volatile variables are not atomic, nor do they establish a
proper happens-before relationship for threading. This is specified in the
relevant standards (C, C++, POSIX, WIN32)..."
"According to the C++11 ISO Standard, the volatile keyword is only meant for
use for hardware access; do not use it for inter-thread communication."
Go read the wikipedia and ask questions here if you still don't understand.
I want to nail this down because I have seen too many people like you on
this and they caused trouble in practice.

【在 d***a 的大作中提到】
: You are wrong.
d***a
发帖数: 13752
40
Your understanding about those statements is wrong. What SSA said is
consistent with those statements.
What's why a CS major should have solid training in computer organization,
assembly programming, and complier construction. Otherwise, one may not even
know what he/she is talking about.

for

【在 F****n 的大作中提到】
: https://en.wikipedia.org/wiki/Volatile_(computer_programming)
: Quotes:
: "Operations on volatile variables are not atomic, nor do they establish a
: proper happens-before relationship for threading. This is specified in the
: relevant standards (C, C++, POSIX, WIN32)..."
: "According to the C++11 ISO Standard, the volatile keyword is only meant for
: use for hardware access; do not use it for inter-thread communication."
: Go read the wikipedia and ask questions here if you still don't understand.
: I want to nail this down because I have seen too many people like you on
: this and they caused trouble in practice.

相关主题
问个C++编译器如何处理函数内的static 变量请教一个c语言实现多线程的问题
C++ InitializeCriticalSection问题question about volatile variable on multiple cores
说到cpp11 和 围棋的对比线程共享变量问题,搞不懂。
进入Programming版参与讨论
F****n
发帖数: 3271
41
你就不能谦虚一点?这是他的原话
"volatile 就是告诉 CPU 不要优化这个变量 Load/Store 的操作。
每个 memory load/store 都不能省,是有很明确的结果的。
load/store 的优化一般有:
同一个地方load 多次,中间没有写,后面的load和前面一样。
有多个store,前面的 store 可以去掉,最后一个 store 赢。
volatile 保证没有一个 load/store 被省略了。
其他派生出来的就是如何根据这个原理用而以"
你跟我讲讲“不要优化这个变量 Load/Store 的操作。每个 memory load/store 都不
能省”
和C/C++的定义符合的?
恰恰相反,完全错误!
C/C++ volatile周围的load/stores可以随意被reorder优化!因为C/C++不像Java,它
的语言定义不包含内存模型,所谓的load/store这些东西,对C/C++语言本身来说是没
有任何意义的。而volatile是语言定义的一部分,自然也和load/store这些无关。
Memory model在C/C++里是通过atomic库来实现的。

even

【在 d***a 的大作中提到】
: Your understanding about those statements is wrong. What SSA said is
: consistent with those statements.
: What's why a CS major should have solid training in computer organization,
: assembly programming, and complier construction. Otherwise, one may not even
: know what he/she is talking about.
:
: for

d***a
发帖数: 13752
42
你没学过computer organization和assembly programming吧。SSA说的明显是对的,那
是CS本科必修课中的基本内容里的东西。
https://users.info.uvt.ro/~iordan/P_I/Ritchie-Kernighan-The_C_Programming_
Language_2_ed.pdf, page 232
The purpose of volatile is to force an implementation to suppress
optimization that could otherwise occur. For example, for a machine with
memory-mapped input/output, a pointer to a device register might be declared
as a pointer to volatile, in order to prevent the compiler from removing
apparently redundant references through the pointer.
"in order to prevent the compiler from removing apparently redundant
references", 在load/store的处理器架构上,指的就是不要去掉在正常优化下本来可
以去掉的load/store指令。
你要不要我给你写两段汇编代码,展示一下有volatile和没有volatile的区别?
PS SSA的原文有小的失误,"volatile就是告诉CPU不要优化这个变量Load/Store
的操作",应该是告诉compiler,不是告诉CPU。但对知道这个topic的人来说,不
会因此有误解。

【在 F****n 的大作中提到】
: 你就不能谦虚一点?这是他的原话
: "volatile 就是告诉 CPU 不要优化这个变量 Load/Store 的操作。
: 每个 memory load/store 都不能省,是有很明确的结果的。
: load/store 的优化一般有:
: 同一个地方load 多次,中间没有写,后面的load和前面一样。
: 有多个store,前面的 store 可以去掉,最后一个 store 赢。
: volatile 保证没有一个 load/store 被省略了。
: 其他派生出来的就是如何根据这个原理用而以"
: 你跟我讲讲“不要优化这个变量 Load/Store 的操作。每个 memory load/store 都不
: 能省”

F****n
发帖数: 3271
43
你引用的原话里讲的包括
1. memory mapped IO,
2. a pointer to a device register
这两个跟他说的memory load/store 有什么关系? 你不会不清楚memory model是啥?
这两个就是我前面讲的跟硬件访问有关,现在的应用非常少,跟线程没有半点关系。
可笑的是不懂装懂,半瓶水响叮当,还computer organization和assembly
programming,真是无语了。

declared

【在 d***a 的大作中提到】
: 你没学过computer organization和assembly programming吧。SSA说的明显是对的,那
: 是CS本科必修课中的基本内容里的东西。
: https://users.info.uvt.ro/~iordan/P_I/Ritchie-Kernighan-The_C_Programming_
: Language_2_ed.pdf, page 232
: The purpose of volatile is to force an implementation to suppress
: optimization that could otherwise occur. For example, for a machine with
: memory-mapped input/output, a pointer to a device register might be declared
: as a pointer to volatile, in order to prevent the compiler from removing
: apparently redundant references through the pointer.
: "in order to prevent the compiler from removing apparently redundant

b***i
发帖数: 3043
44
我觉得研究问题不能太教条,到现在还没人给出为什么不对的原因,只是引用标准和
wiki,那只是一般来说的情况。
首先,我觉得atomic不是个事。在UI里面写这个变量,或者在TCP等待的线程里面写这
个变量,又不是读完再加一再写,到底能有什么atomic问题,请指出。就一个bool,到
底能有什么问题?
第二,读写顺序又有什么关系?就一个通知各线程退出的变量,也没有其他操作,可以
吗?UI/TCP的回叫函数里面改写这个变量为真然后函数退出。那么,根本没有happens-
before关系。没有任何其他变量的改写。
void uicallback(){
quit=true;//此前此后没有任何其他赋值
}
或者
void processTCPcallback(...){
if ...
if (condition)
quit=true;//此if前此后没有任何其他赋值
if ...
}
另外,前面有人说过什么busy waiting,也是没啥关系。这个线程里面不是一直在读这
个变量,读一次之后要做很多事情,比如10毫秒的工作。就是说这个while循环大概10
毫秒甚至1毫秒就读这个变量一次。置于这个变量改了之后,是不是线程立刻退出了,
那没啥关系。只要10-20毫秒内退出就行。
我希望大家讨论要根据这些具体的信息,而不是普通情况,而且要具体的不能用的原因
。都知道普通的多线程信息处理不能这样做。
基本情况就是,希望用Linux, 用C++,多线程,可能多CPU/多核心,CPU可能是x86,
x64, ARM等各类能够运行Linux的CPU。

for

【在 F****n 的大作中提到】
: https://en.wikipedia.org/wiki/Volatile_(computer_programming)
: Quotes:
: "Operations on volatile variables are not atomic, nor do they establish a
: proper happens-before relationship for threading. This is specified in the
: relevant standards (C, C++, POSIX, WIN32)..."
: "According to the C++11 ISO Standard, the volatile keyword is only meant for
: use for hardware access; do not use it for inter-thread communication."
: Go read the wikipedia and ask questions here if you still don't understand.
: I want to nail this down because I have seen too many people like you on
: this and they caused trouble in practice.

c*********e
发帖数: 16335
45
compiler会打乱你的代码的顺序的。很多东西别想当然。你的代码要先经过compiler,
后来还要runtime.这些都不是你能控制的。

happens-

【在 b***i 的大作中提到】
: 我觉得研究问题不能太教条,到现在还没人给出为什么不对的原因,只是引用标准和
: wiki,那只是一般来说的情况。
: 首先,我觉得atomic不是个事。在UI里面写这个变量,或者在TCP等待的线程里面写这
: 个变量,又不是读完再加一再写,到底能有什么atomic问题,请指出。就一个bool,到
: 底能有什么问题?
: 第二,读写顺序又有什么关系?就一个通知各线程退出的变量,也没有其他操作,可以
: 吗?UI/TCP的回叫函数里面改写这个变量为真然后函数退出。那么,根本没有happens-
: before关系。没有任何其他变量的改写。
: void uicallback(){
: quit=true;//此前此后没有任何其他赋值

c*********e
发帖数: 16335
46
volatile和atomic没有关系。
volatile是说到共享的memory里去找这个变量的值。
atomic是说是原子操作。

promoted
adds

【在 F****n 的大作中提到】
: That's not correct. Java volatile is fine. It is equivalent to atomic
: without compare.
: I don't buy this immutable thing. Like design patterns, it is over-promoted
: by biblical theorists with little practical experience, and it normally adds
: a lot of unnecessary crap to a simple problem.

b***i
发帖数: 3043
47
我这个quit变量的赋值前后没有其他赋值,所以compiler怎么打乱?

【在 c*********e 的大作中提到】
: compiler会打乱你的代码的顺序的。很多东西别想当然。你的代码要先经过compiler,
: 后来还要runtime.这些都不是你能控制的。
:
: happens-

b***i
发帖数: 3043
48
那bool(非atomic)到底为什么不是原子的?就一个bit难道不是最基本的构成?难道还
能三极管电压到达一半的程度?无法理解

【在 c*********e 的大作中提到】
: volatile和atomic没有关系。
: volatile是说到共享的memory里去找这个变量的值。
: atomic是说是原子操作。
:
: promoted
: adds

c*********e
发帖数: 16335
49
网上抄的一个例子:
The belowcode snippet is not thread-safe
bool initialized;
if (!initialized) {
initialize();
initialized = true;
}
Hence in such situation, we fix it usingAtomic Boolean
AtomicBoolean initialized= new AtomicBoolean(false);
if (initialized.compareAndSet(false, true)) {
initialize();
}

【在 b***i 的大作中提到】
: 那bool(非atomic)到底为什么不是原子的?就一个bit难道不是最基本的构成?难道还
: 能三极管电压到达一半的程度?无法理解

a9
发帖数: 21638
50
我觉得他那个完全没问题
你这个例子跟他的用法完全不是一回事儿,他只是在另一个线程里置个标志位而已。
大不子多跑一个循环10毫秒应该不影响他的结果

道还

【在 c*********e 的大作中提到】
: 网上抄的一个例子:
: The belowcode snippet is not thread-safe
: bool initialized;
: if (!initialized) {
: initialize();
: initialized = true;
: }
: Hence in such situation, we fix it usingAtomic Boolean
: AtomicBoolean initialized= new AtomicBoolean(false);
: if (initialized.compareAndSet(false, true)) {

相关主题
How to use volatile in c++?关于signal handler
java的同步问题请教问达人一个shared memory 的问题
Concurrency of assignment statement in C用STL map的时候怎么自己定义大小比较的关系
进入Programming版参与讨论
p***o
发帖数: 1252
51
这个问题讨论这么久你还没明白什么重要。
首先现在既然有C++11的标准了,当然要遵循标准。你要是觉得按标准写程序是教条,
那后面就没啥好说的了。
其次按标准来说,Foxman说的很对。你的疑惑在于不明白什么叫memory barrier。
这个东西别指望学校里能教,量化研究方法这种研究生体系结构教科书上都只花了
一页介绍,别提本科级别的汇编语言和体系结构课了。
最后,C++的std::atomic带memory barrier,这个是你需要的,至于CAS这样的atomic
操作那是另外的功能。另外java里的volatile和C++里的完全不一样,前面也讨论的很
清楚了。

happens-

【在 b***i 的大作中提到】
: 我觉得研究问题不能太教条,到现在还没人给出为什么不对的原因,只是引用标准和
: wiki,那只是一般来说的情况。
: 首先,我觉得atomic不是个事。在UI里面写这个变量,或者在TCP等待的线程里面写这
: 个变量,又不是读完再加一再写,到底能有什么atomic问题,请指出。就一个bool,到
: 底能有什么问题?
: 第二,读写顺序又有什么关系?就一个通知各线程退出的变量,也没有其他操作,可以
: 吗?UI/TCP的回叫函数里面改写这个变量为真然后函数退出。那么,根本没有happens-
: before关系。没有任何其他变量的改写。
: void uicallback(){
: quit=true;//此前此后没有任何其他赋值

g****t
发帖数: 31659
52
他可能不理解这些东西的design motivation。
这类东西的根源,除了多线程,最容易理解的需求根源
是硬件驱动。这些往往是EE的内容。


: 这个问题讨论这么久你还没明白什么重要。

: 首先现在既然有C 11的标准了,当然要遵循标准。你要是觉得按标准写
程序是
教条,

: 那后面就没啥好说的了。

: 其次按标准来说,Foxman说的很对。你的疑惑在于不明白什么叫memory
barrier。

: 这个东西别指望学校里能教,量化研究方法这种研究生体系结构教科书上
都只花了

: 一页介绍,别提本科级别的汇编语言和体系结构课了。

: 最后,C 的std::atomic带memory barrier,这个是你需要的,至于CAS
这样的
atomic

: 操作那是另外的功能。另外java里的volatile和C 里的完全不一样,前
面也讨
论的很

: 清楚了。

: happens-



【在 p***o 的大作中提到】
: 这个问题讨论这么久你还没明白什么重要。
: 首先现在既然有C++11的标准了,当然要遵循标准。你要是觉得按标准写程序是教条,
: 那后面就没啥好说的了。
: 其次按标准来说,Foxman说的很对。你的疑惑在于不明白什么叫memory barrier。
: 这个东西别指望学校里能教,量化研究方法这种研究生体系结构教科书上都只花了
: 一页介绍,别提本科级别的汇编语言和体系结构课了。
: 最后,C++的std::atomic带memory barrier,这个是你需要的,至于CAS这样的atomic
: 操作那是另外的功能。另外java里的volatile和C++里的完全不一样,前面也讨论的很
: 清楚了。
:

h**********c
发帖数: 4120
53
it is f*cking s*ck, 解决问题远远让位于defending turf, even nobody where is
knows turfen is.
叔在这里透其实也都是早都讨论过的。当年good bug 在这里unix network
programming,叔还在提过的讨论,看看JVM unsafe那段C代码。
d***a
发帖数: 13752
54
老兄,你半懂不懂啊。你不是科班出身的,对吧。
volatile的基本含义就是如SSA所说,那是CS本科课程基础内容。你后来贴的wiki说法
,和SSA说的并不矛盾之处。这是为什么我说,you don't really know what you're
talking about。
楼主该不该用volatile, 和volatile是什么含义,从逻辑上说是两个不同的问题。
就楼主的代码而言,volatile就够了。他的代码的问题不在这里。

【在 F****n 的大作中提到】
: 你引用的原话里讲的包括
: 1. memory mapped IO,
: 2. a pointer to a device register
: 这两个跟他说的memory load/store 有什么关系? 你不会不清楚memory model是啥?
: 这两个就是我前面讲的跟硬件访问有关,现在的应用非常少,跟线程没有半点关系。
: 可笑的是不懂装懂,半瓶水响叮当,还computer organization和assembly
: programming,真是无语了。
:
: declared

d***a
发帖数: 13752
55
你的代码只有一次写共享变量,用不用atomic都可以。有多次写共享变量的情况下,就
要注意多次写的排序的问题,你的代码不是这样。
一般性的并行代码,会有多次写共享变量。那种情况下,用atomic比较安全。
你的代码,是运行不对吗? 我觉的首先要查的是控制结构与线程优先级。如果你用了多线
程,线程优先级设置不对,quit = true可能得不到执行的机会。如果你用了UI回调函数
(执行优先级高),那可能是别的什么地方不对, 但也要看具体用的是什么UI系统。
另外,你说的TCP的回调函数,具体是什么呢?

happens-

【在 b***i 的大作中提到】
: 我觉得研究问题不能太教条,到现在还没人给出为什么不对的原因,只是引用标准和
: wiki,那只是一般来说的情况。
: 首先,我觉得atomic不是个事。在UI里面写这个变量,或者在TCP等待的线程里面写这
: 个变量,又不是读完再加一再写,到底能有什么atomic问题,请指出。就一个bool,到
: 底能有什么问题?
: 第二,读写顺序又有什么关系?就一个通知各线程退出的变量,也没有其他操作,可以
: 吗?UI/TCP的回叫函数里面改写这个变量为真然后函数退出。那么,根本没有happens-
: before关系。没有任何其他变量的改写。
: void uicallback(){
: quit=true;//此前此后没有任何其他赋值

b***i
发帖数: 3043
56
我并没有在实践中发现问题,只是问个理论的问题。
具体的TCP就是判断收到字符串"QUIT",那么就要求各线程退出。

多线
函数

【在 d***a 的大作中提到】
: 你的代码只有一次写共享变量,用不用atomic都可以。有多次写共享变量的情况下,就
: 要注意多次写的排序的问题,你的代码不是这样。
: 一般性的并行代码,会有多次写共享变量。那种情况下,用atomic比较安全。
: 你的代码,是运行不对吗? 我觉的首先要查的是控制结构与线程优先级。如果你用了多线
: 程,线程优先级设置不对,quit = true可能得不到执行的机会。如果你用了UI回调函数
: (执行优先级高),那可能是别的什么地方不对, 但也要看具体用的是什么UI系统。
: 另外,你说的TCP的回调函数,具体是什么呢?
:
: happens-

b***i
发帖数: 3043
57
我觉得不是memory barrier的问题。memory barrier前面有很多人提过,就是会防止打
乱次序。可是我代码里面设置quit=true;的语句前后没有其他代码。总不能把if的条件
和结果给打乱了吧?
UI回叫
void UIcallback(...){
quit=true;//这里没有任何其他语句
}
或者TCP处理的回叫
void TCPcallback(...){
...A
if (字符串=="QUIT")
quit=true;//这里没有任何其他语句
else
...B
...C
}
有个if在那里总不能把...A和quit=true;交换顺序吧?在这里即使有A/C这两个语句,
也是和quit=true互斥的,就是说我不可能在线程需要退出了还要继续进行其他的操作
。如果有人问那一定要进行其他的操作怎么办,比如释放资源。办法很简单,在线程的
while结束后操作。所以我说很多人引经据典都是对普通的情况的建议。对我这种具体
的情况,就一个bool,所以不需要critical section,就一个赋值,赋值前后没有其他
赋值,所以也不应该有memory barrier问题。
现在我倒是发现一个具体的问题,就是volatile不能保证信息是从内存读的,它只能保
证读入。这个读可能是cache里面的。那么多CPU就不能防止这个问题了。
stackoverflow上查Can I force cache coherency on a multicore x86 CPU?看到说多
CPU可能会有cache问题。

atomic

【在 p***o 的大作中提到】
: 这个问题讨论这么久你还没明白什么重要。
: 首先现在既然有C++11的标准了,当然要遵循标准。你要是觉得按标准写程序是教条,
: 那后面就没啥好说的了。
: 其次按标准来说,Foxman说的很对。你的疑惑在于不明白什么叫memory barrier。
: 这个东西别指望学校里能教,量化研究方法这种研究生体系结构教科书上都只花了
: 一页介绍,别提本科级别的汇编语言和体系结构课了。
: 最后,C++的std::atomic带memory barrier,这个是你需要的,至于CAS这样的atomic
: 操作那是另外的功能。另外java里的volatile和C++里的完全不一样,前面也讨论的很
: 清楚了。
:

d***a
发帖数: 13752
58
这样的话,你的代码结构上没有问题,也是实际代码中比较常见的做法。Flag变量用
volatile可以。
不过,如果计算的部分并行化了,分成多个线程并且交换数据,那flag变量确实应该用
atomic。这样做可以保证每个线程看到flag的变化后,读到的共享数据是fresh的而不
是旧的。你的程序除了flag之外没有共享数据交换,所以没事。

【在 b***i 的大作中提到】
: 我并没有在实践中发现问题,只是问个理论的问题。
: 具体的TCP就是判断收到字符串"QUIT",那么就要求各线程退出。
:
: 多线
: 函数

d***a
发帖数: 13752
59
呵呵,barrier操作是parallel computing课中最基本的内容。但外系的学生来计算机
系修课,一般不会选parallel computing, 计算机系的学生也不是每个人都学。
楼主的程序并不需要memory barrier。Foxman的问题是并没有把情况搞清楚,死板地应
用概念,过于自以为是。

atomic

【在 p***o 的大作中提到】
: 这个问题讨论这么久你还没明白什么重要。
: 首先现在既然有C++11的标准了,当然要遵循标准。你要是觉得按标准写程序是教条,
: 那后面就没啥好说的了。
: 其次按标准来说,Foxman说的很对。你的疑惑在于不明白什么叫memory barrier。
: 这个东西别指望学校里能教,量化研究方法这种研究生体系结构教科书上都只花了
: 一页介绍,别提本科级别的汇编语言和体系结构课了。
: 最后,C++的std::atomic带memory barrier,这个是你需要的,至于CAS这样的atomic
: 操作那是另外的功能。另外java里的volatile和C++里的完全不一样,前面也讨论的很
: 清楚了。
:

F****n
发帖数: 3271
60
还在不懂装懂,建议回去好好问问懂C/C++的人

【在 d***a 的大作中提到】
: 呵呵,barrier操作是parallel computing课中最基本的内容。但外系的学生来计算机
: 系修课,一般不会选parallel computing, 计算机系的学生也不是每个人都学。
: 楼主的程序并不需要memory barrier。Foxman的问题是并没有把情况搞清楚,死板地应
: 用概念,过于自以为是。
:
: atomic

相关主题
C++ template questionone more c++ question
how to write some C/C++ program to enable dual monitor?Bihai,你就用atmoic完事了
请教: 用stable_sort 在VC++下通过但在g++下通不过Volatile variables do not provide any atomicity (转载)
进入Programming版参与讨论
w***g
发帖数: 5958
61
我就没学过,后来stackoverflow上学的。不过我承认我上parallel architecture
研究生课的时候一路都在打瞌睡。我曾经有跟楼主差不多的需要,纠结过一番
memory barrier,最后还是老老实实用了std::condition_variable。代码在这里
https://github.com/aaalgo/picpac/blob/master/picpac.h
省心,扩展容易,代码干净。
其实这种情况出现过多次,每次都觉得这么简单的情况不需要杀鸡用牛刀,
最后挖下去都发现水太深,然后用牛刀了事。
我印象中,操统课会讲IPC objects, mutex, sophomore这种。这些都是普世价值,
性能肯定有代价,但是一般没有坑。

【在 d***a 的大作中提到】
: 呵呵,barrier操作是parallel computing课中最基本的内容。但外系的学生来计算机
: 系修课,一般不会选parallel computing, 计算机系的学生也不是每个人都学。
: 楼主的程序并不需要memory barrier。Foxman的问题是并没有把情况搞清楚,死板地应
: 用概念,过于自以为是。
:
: atomic

d***a
发帖数: 13752
62
握手。你PhD导师是这个领域的大牛啊,他的PhD论文我读过。
我以前有一段时间被迫搞过并行程序的性能优化,那个烦人,现有的轮子都不能用(性
能问题)。
bihai的代码,确实是用标准的IPC机制就可以的。我前面也给他说过,一般是用signal。
UI进程发个信号给计算进程,计算进程写个信号处理handler来做退出,就可以了。这
样做的好处就是绕过了底层那些nasty的细节。当然他的做法,小心一点也是可以的。
搞嵌入式编程的人喜欢用那种方式。

【在 w***g 的大作中提到】
: 我就没学过,后来stackoverflow上学的。不过我承认我上parallel architecture
: 研究生课的时候一路都在打瞌睡。我曾经有跟楼主差不多的需要,纠结过一番
: memory barrier,最后还是老老实实用了std::condition_variable。代码在这里
: https://github.com/aaalgo/picpac/blob/master/picpac.h
: 省心,扩展容易,代码干净。
: 其实这种情况出现过多次,每次都觉得这么简单的情况不需要杀鸡用牛刀,
: 最后挖下去都发现水太深,然后用牛刀了事。
: 我印象中,操统课会讲IPC objects, mutex, sophomore这种。这些都是普世价值,
: 性能肯定有代价,但是一般没有坑。

F****n
发帖数: 3271
63
那你加volatile的目的是什么?
你也知道cache访问会有问题,
这就是exactly memory barrier, reordering这些讲的东西
你的quit=true只要被调用周围就灰有代码。

【在 b***i 的大作中提到】
: 我觉得不是memory barrier的问题。memory barrier前面有很多人提过,就是会防止打
: 乱次序。可是我代码里面设置quit=true;的语句前后没有其他代码。总不能把if的条件
: 和结果给打乱了吧?
: UI回叫
: void UIcallback(...){
: quit=true;//这里没有任何其他语句
: }
: 或者TCP处理的回叫
: void TCPcallback(...){
: ...A

c*********e
发帖数: 16335
64
对呀。我说了,volatile一般也就用在bool上,如果把volatile用在什么collection上
,就不好了。

【在 a9 的大作中提到】
: 我觉得他那个完全没问题
: 你这个例子跟他的用法完全不是一回事儿,他只是在另一个线程里置个标志位而已。
: 大不子多跑一个循环10毫秒应该不影响他的结果
:
: 道还

F****n
发帖数: 3271
65
这个就是悖论,他那个condition只要被调用就会有代码
只有从来不会被调用才会完全没问题的
还有一种情况,并行计算中其实有些时候各个进程/线程之间的状态并不需要一致,
如果是这种情况下确实没问题,但是也不需要volatile,什么都不需要。
既然用了volatile就是对一致性有要求,不能说"我这个程序其实不需要一致性所以没
问题”。那你弄volatile是啥目的?
最后,C/C++和Java一个很大的不同就是C/C++很多情况下是全局优化,很多时候你根本
不能假设你的变量最后会怎么样,因为别人可能会调用你的code,然后别人调用代码周
围那些指令,和你的指令会被合在一起优化。

【在 a9 的大作中提到】
: 我觉得他那个完全没问题
: 你这个例子跟他的用法完全不是一回事儿,他只是在另一个线程里置个标志位而已。
: 大不子多跑一个循环10毫秒应该不影响他的结果
:
: 道还

w***g
发帖数: 5958
66
楼上帮我看看下面的说法有没有问题。
memory barrier有两种:
1. soft barrier: 阻止编译器乱优化。一般以volatile关键字的形式出现。编译后不
会产生对应的指令。有时候-O3出错,但是-O0对了,肯定是缺了soft barrier。
2. hard barrier: 阻止CPU乱执行。一般是以汇编指令/intrinsics的方式出现。改优
化级别不能解决hard barrier用错的问题。
外加一个独立的atomicity问题。
memory barrier和atomicity是两个不同的问题。比如a = a+ 1这个操作,涉及读/算/
写,即使用了memory barrier,在多线程之下还是会出问题。然而反过来,要保证
atomicity必须得用hard barrier。所以gcc的__sync_fetch_and_xxx系列指令全都有
hard barrier
的效果。std::atomic对于基本类型应该就是编译成__sync_fetch_and_xxx,复杂类型
应该是用锁实现,间接涉及__sync指令。所以不管怎样,也都有hard barrier的效果。
那么问题来了:gcc碰到hard barrier时会不会自动塞入soft barrier?
能不能举出一个例子,就是光用__sync_xxx还不够,非得用volatile才行的?
(另一个对称的问题,能不能举出一个例子,光用volatile就够了,不需要
__sync_xxx。这个问题的答案我相信就是楼主这个spin wait的问题。)
Update:
答案来了:gcc下__sync_synchronize()有volatile的作用。
int no_volatile_no_sync (int *i) {
*i = 1;
*i = 2;
}
int no_volatile_sync (int *i) {
*i = 1;
__sync_synchronize();
*i = 2;
}
如果用-O3编译,第一个输出为:
movl $2, (%rdi)
ret
第二个输出为
movl $1, (%rdi)
mfence
movl $2, (%rdi)
ret
除了__sync_xxx直接对应的mfence,前面那个赋值没有被优化掉。
我怀疑正因为gcc下hard barrier隐含soft barrier,所以导致网上盛行的一种
说法,就是volatile关键字没用。
Update 2:
硬加入mfence
int no_volatile_mfence (int *i) {
*i = 1;
asm("mfence");
*i = 2;
}
输出
mfence
movl $2, (%rdi)
ret
第一条赋值被干掉了。而改成asm("":::"memory")则会保留赋值。
所以__sync_synchronize等价于asm("mfence")和asm("":::"memory")联合用。

【在 F****n 的大作中提到】
: 这个就是悖论,他那个condition只要被调用就会有代码
: 只有从来不会被调用才会完全没问题的
: 还有一种情况,并行计算中其实有些时候各个进程/线程之间的状态并不需要一致,
: 如果是这种情况下确实没问题,但是也不需要volatile,什么都不需要。
: 既然用了volatile就是对一致性有要求,不能说"我这个程序其实不需要一致性所以没
: 问题”。那你弄volatile是啥目的?
: 最后,C/C++和Java一个很大的不同就是C/C++很多情况下是全局优化,很多时候你根本
: 不能假设你的变量最后会怎么样,因为别人可能会调用你的code,然后别人调用代码周
: 围那些指令,和你的指令会被合在一起优化。

d***a
发帖数: 13752
67
再加一个函数,看编译优化输出的代码,更清楚一些:
int volatile_no_sync (volatile int *i) {
*i = 1;
*i = 2;
}
汇编代码:
_no_volatile_no_sync
movl $2, (%rdi)
ret
_volatile_no_sync
movl $1, (%rdi)
movl $2, (%rdi)
ret
_no_volatile_sync
movl $1, (%rdi)
mfence
movl $2, (%rdi)
ret
我前面说过,如果从组织结构和代码生成的角度来看volatile和atomic,其实是很简单
的。volatile的作用就是要编译器不要去掉“多余”的内存访问;在load/store处理器
架构上是load/store指令,在x86架构上是有内存访问的mov指令。

【在 w***g 的大作中提到】
: 楼上帮我看看下面的说法有没有问题。
: memory barrier有两种:
: 1. soft barrier: 阻止编译器乱优化。一般以volatile关键字的形式出现。编译后不
: 会产生对应的指令。有时候-O3出错,但是-O0对了,肯定是缺了soft barrier。
: 2. hard barrier: 阻止CPU乱执行。一般是以汇编指令/intrinsics的方式出现。改优
: 化级别不能解决hard barrier用错的问题。
: 外加一个独立的atomicity问题。
: memory barrier和atomicity是两个不同的问题。比如a = a+ 1这个操作,涉及读/算/
: 写,即使用了memory barrier,在多线程之下还是会出问题。然而反过来,要保证
: atomicity必须得用hard barrier。所以gcc的__sync_fetch_and_xxx系列指令全都有

b***i
发帖数: 3043
68
我觉得cache的问题和memory barrier不是同一个问题。所以我一直认为reordering在
这里不会产生任何问题。
你想啊,我让线程退出,我还能有什么有用的信息告诉线程呢?会有什么错误呢?线程
都要退出了,做什么都不重要了。并不是我要传递几个参数,然后改写一个bool的变量
,然后希望线程读入那几个变量。这里除了quit没有任何其他变量的读写

【在 F****n 的大作中提到】
: 那你加volatile的目的是什么?
: 你也知道cache访问会有问题,
: 这就是exactly memory barrier, reordering这些讲的东西
: 你的quit=true只要被调用周围就灰有代码。

p***o
发帖数: 1252
69
你得分清楚标准和实现。按C++标准,volatile不需要带barrier/ordering,
std::atomic可以按你的需要选定几种ordering中的一个,包括你说的soft/hard。
事实上对程序员来说soft/hard应该保持一致,要不然程序就没法写了。

【在 w***g 的大作中提到】
: 楼上帮我看看下面的说法有没有问题。
: memory barrier有两种:
: 1. soft barrier: 阻止编译器乱优化。一般以volatile关键字的形式出现。编译后不
: 会产生对应的指令。有时候-O3出错,但是-O0对了,肯定是缺了soft barrier。
: 2. hard barrier: 阻止CPU乱执行。一般是以汇编指令/intrinsics的方式出现。改优
: 化级别不能解决hard barrier用错的问题。
: 外加一个独立的atomicity问题。
: memory barrier和atomicity是两个不同的问题。比如a = a+ 1这个操作,涉及读/算/
: 写,即使用了memory barrier,在多线程之下还是会出问题。然而反过来,要保证
: atomicity必须得用hard barrier。所以gcc的__sync_fetch_and_xxx系列指令全都有

F****n
发帖数: 3271
70
我发现明明我一直在说reorder,你却一直在说省
我建议你再仔细看看我批评的那个帖子的原话,他说的是“优化”。

【在 d***a 的大作中提到】
: 再加一个函数,看编译优化输出的代码,更清楚一些:
: int volatile_no_sync (volatile int *i) {
: *i = 1;
: *i = 2;
: }
: 汇编代码:
: _no_volatile_no_sync
: movl $2, (%rdi)
: ret
: _volatile_no_sync

相关主题
Volatile variables do not provide any atomicity (转载)C++ InitializeCriticalSection问题
关于线程读写全局变量的问题说到cpp11 和 围棋的对比
问个C++编译器如何处理函数内的static 变量请教一个c语言实现多线程的问题
进入Programming版参与讨论
d***a
发帖数: 13752
71
你啊,洗洗睡吧。你写的东西,不客气也说,没什么好看的。你没有足够的training,
又太自以为是了。

【在 F****n 的大作中提到】
: 我发现明明我一直在说reorder,你却一直在说省
: 我建议你再仔细看看我批评的那个帖子的原话,他说的是“优化”。

F****n
发帖数: 3271
72
cache access 和 memory barrier 从reorder 优化的角度是一个道理
为什么recorder优化可行?是因为compiler发现你程序某些部分并不互相关联
所以把顺序换换也没关系。但在并行计算的情况下compiler很难通过语义分析(对C/C+
+来说)确定关联性,所以需要额外的memory barrier,它的一个作用就是把一定的顺
序强加在使用不同cache但访问同样内存地址区的并行进程。
为什么决大多数情况下用volatile退出线程不对? 简单的说,因为有数据一致性
要求时volatile不工作,没有数据一致性要求时,你根本不需要volatile。大多数情况
下你总不可能什么都不做就直接quit吧?总要对一些数据进行操作和判断然后决定是否
quit。举个不太恰当的例子:
Connection conn; // assumed to be a db connection;
bool volatile quit;
...
while (!quit) {
conn.doSomething(); // error if conn is closed
parkThread(100); //
}
if (conn.isOpen()) {
conn.close();
}
如果这是你的worker的逻辑,可能出现的问题是你点了quit button后,一个线程先
refresh发现quit变成了true 于是call conn.close(),但另一个线程的cache里 quit
还是false,还在call doSomething()。
可能很多人已经注意到了,其实如果conn.doSomething()自带logic检验是否close,上
面的程序就不会有任何问题。但如果这样的话,你会发现其实你也用不着volatile! 因
为你的数据conn已经不存在一致性问题了!这就是为什么C/C++里volatile大多数情况
下无用的原因:如果数据需要一致,用volatile是bug; 如果数据不需要一直,根本用
不着volatile。
前面已经讲了,C/C++ volatile唯一的作用就是让compiler不要把变量读写操作
optimize away。但这个作用实际上也是鸡肋。C/C++是全局编译优化,只要在编译单位
的任何一个地方出现了对“quit"的写操作,即使你自己的code里没有,别人import你
的code只要有,compiler就不会把他扔掉。一般来说,既然要通过quit来控制线程,就
必然在某些地方会对其进行写操作,所以volatile也就没什么用。只有少数几种情况是
例外,比如如果把quit map到一个shared memory区,然后完全由3rd party来update,
那么你的编译单位确实可以没有对quit的写操作,此时确实需要加volatile来防止编译
优化。这就是C/C++标准提到的volatile的几个use case,在实际应用中是比较罕见的。

【在 b***i 的大作中提到】
: 我觉得cache的问题和memory barrier不是同一个问题。所以我一直认为reordering在
: 这里不会产生任何问题。
: 你想啊,我让线程退出,我还能有什么有用的信息告诉线程呢?会有什么错误呢?线程
: 都要退出了,做什么都不重要了。并不是我要传递几个参数,然后改写一个bool的变量
: ,然后希望线程读入那几个变量。这里除了quit没有任何其他变量的读写

F****n
发帖数: 3271
73
还在不懂装懂,这句话是你赞成的那个帖子的原话:
"volatile 就是告诉 CPU 不要优化这个变量 Load/Store 的操作”
你就直接说说这句话对不对。

【在 d***a 的大作中提到】
: 你啊,洗洗睡吧。你写的东西,不客气也说,没什么好看的。你没有足够的training,
: 又太自以为是了。

F****n
发帖数: 3271
74
你说的没错,__sync_fetch_and_xxx包括compiler barrier,文档里有提。
但C/C++里volatile没用的原因主要还是因为多数情况下,省略不省略和内存访问顺序
比,实在不重要。省略最多会漏掉一些初始值,顺序不对问题就大条了。所以gcc干脆
把compiler barrier 也加上省事。相反VC++则是把volatile变成跟Java一样fully
synchronized.

【在 w***g 的大作中提到】
: 楼上帮我看看下面的说法有没有问题。
: memory barrier有两种:
: 1. soft barrier: 阻止编译器乱优化。一般以volatile关键字的形式出现。编译后不
: 会产生对应的指令。有时候-O3出错,但是-O0对了,肯定是缺了soft barrier。
: 2. hard barrier: 阻止CPU乱执行。一般是以汇编指令/intrinsics的方式出现。改优
: 化级别不能解决hard barrier用错的问题。
: 外加一个独立的atomicity问题。
: memory barrier和atomicity是两个不同的问题。比如a = a+ 1这个操作,涉及读/算/
: 写,即使用了memory barrier,在多线程之下还是会出问题。然而反过来,要保证
: atomicity必须得用hard barrier。所以gcc的__sync_fetch_and_xxx系列指令全都有

a9
发帖数: 21638
75
你这是设计有问题。
如果你两个线程都要用数据库连接,那应该各自建一个单独的连接
或者在主线程里建连接,起两个线程,设置quit=true,等两个线程退出,然后断开连接
线程处理本来应该是相对独立的逻辑,你这种处理法用不用线程有什么意义吗

C+
quit
的。
reordering在
线程
变量

【在 F****n 的大作中提到】
: cache access 和 memory barrier 从reorder 优化的角度是一个道理
: 为什么recorder优化可行?是因为compiler发现你程序某些部分并不互相关联
: 所以把顺序换换也没关系。但在并行计算的情况下compiler很难通过语义分析(对C/C+
: +来说)确定关联性,所以需要额外的memory barrier,它的一个作用就是把一定的顺
: 序强加在使用不同cache但访问同样内存地址区的并行进程。
: 为什么决大多数情况下用volatile退出线程不对? 简单的说,因为有数据一致性
: 要求时volatile不工作,没有数据一致性要求时,你根本不需要volatile。大多数情况
: 下你总不可能什么都不做就直接quit吧?总要对一些数据进行操作和判断然后决定是否
: quit。举个不太恰当的例子:
: Connection conn; // assumed to be a db connection;

F****n
发帖数: 3271
76
说了是不恰当的例子,手快弄上来没仔细考虑过,将就看看意思就是了。

【在 a9 的大作中提到】
: 你这是设计有问题。
: 如果你两个线程都要用数据库连接,那应该各自建一个单独的连接
: 或者在主线程里建连接,起两个线程,设置quit=true,等两个线程退出,然后断开连接
: 线程处理本来应该是相对独立的逻辑,你这种处理法用不用线程有什么意义吗
:
: C+
: quit
: 的。
: reordering在
: 线程

b***i
发帖数: 3043
77
我后来又查了,cache根本就是更无关的,所有volatile退出线程是没有问题的。
就是说,既没有memory barrier问题,也没有原子操作问题。
没有memory barrier是因为设置quit的时候之前之后没有任何操作。如果你有操作需要
做可以在等待线程结束后的主线程那个join那里做。
原子的问题,是因为本来是bool,根本没有问题。
cache是因为本来硬件就是透明的,程序员不需要知道cache存在。
其他方面多线程一般不能使用volatile解决信息传递的问题。但是让线程终止可以,因
为线程都要中止了,还有啥可做的呢?放在Join那里就可以了。

【在 F****n 的大作中提到】
: 你说的没错,__sync_fetch_and_xxx包括compiler barrier,文档里有提。
: 但C/C++里volatile没用的原因主要还是因为多数情况下,省略不省略和内存访问顺序
: 比,实在不重要。省略最多会漏掉一些初始值,顺序不对问题就大条了。所以gcc干脆
: 把compiler barrier 也加上省事。相反VC++则是把volatile变成跟Java一样fully
: synchronized.

g****t
发帖数: 31659
78
我说过了。不了解uncertainty sources的情况,用atomic.
可以假设i = 1的赋值需要500秒,想一想你需要不需要
0到1信号的上升沿完整。
这主要不是个逻辑问题。是个软件的设计问题。就是你要留多少Robustness margin,代
价多高。
你要自己玩。那怎么样都可以。如果要卖出去给人用,massive Users, 那是另一回事。
我看咱们大家可以搁置讨论,5年后再看。


: 我后来又查了,cache根本就是更无关的,所有volatile退出线程是没有问题的。

: 就是说,既没有memory barrier问题,也没有原子操作问题。

: 没有memory barrier是因为设置quit的时候之前之后没有任何操作。如果你有操
作需要

: 做可以在等待线程结束后的主线程那个join那里做。

: 原子的问题,是因为本来是bool,根本没有问题。

: cache是因为本来硬件就是透明的,程序员不需要知道cache存在。

: 其他方面多线程一般不能使用volatile解决信息传递的问题。但是让线程终止可
以,因

: 为线程都要中止了,还有啥可做的呢?放在Join那里就可以了。



【在 b***i 的大作中提到】
: 我后来又查了,cache根本就是更无关的,所有volatile退出线程是没有问题的。
: 就是说,既没有memory barrier问题,也没有原子操作问题。
: 没有memory barrier是因为设置quit的时候之前之后没有任何操作。如果你有操作需要
: 做可以在等待线程结束后的主线程那个join那里做。
: 原子的问题,是因为本来是bool,根本没有问题。
: cache是因为本来硬件就是透明的,程序员不需要知道cache存在。
: 其他方面多线程一般不能使用volatile解决信息传递的问题。但是让线程终止可以,因
: 为线程都要中止了,还有啥可做的呢?放在Join那里就可以了。

b***i
发帖数: 3043
79
我们还真遇到这个问题,一个员工发现数字电路控制的开关除了问题,把电容给爆了。
怎么回事呢?
他的代码是这样的
if (toomuch==1)
op1...
if (toomuch==0)
op2
我一眼就发现了问题。这个toomuch是模拟信号,直接和数字信号1/0比较那么会遇到你
说的情况,在某个区间会既可能是1,又可能是0.而解决的方案是,把是1还是0的判断
做且只一次,再进行op1/op2,否则会出现两个都进行的情况。
if (toomuch)
toomuch_delayed = 1;
else
toomuch_delayed = 0;
...
if (toomuch_delayed)
op1...
所以你说的这个情况也是可以避免的,延时一个时钟即可。

事。
的。

【在 g****t 的大作中提到】
: 我说过了。不了解uncertainty sources的情况,用atomic.
: 可以假设i = 1的赋值需要500秒,想一想你需要不需要
: 0到1信号的上升沿完整。
: 这主要不是个逻辑问题。是个软件的设计问题。就是你要留多少Robustness margin,代
: 价多高。
: 你要自己玩。那怎么样都可以。如果要卖出去给人用,massive Users, 那是另一回事。
: 我看咱们大家可以搁置讨论,5年后再看。
:
:
: 我后来又查了,cache根本就是更无关的,所有volatile退出线程是没有问题的。
:
: 就是说,既没有memory barrier问题,也没有原子操作问题。

1 (共1页)
进入Programming版参与讨论
相关主题
C++ template questionC++ InitializeCriticalSection问题
how to write some C/C++ program to enable dual monitor?说到cpp11 和 围棋的对比
请教: 用stable_sort 在VC++下通过但在g++下通不过请教一个c语言实现多线程的问题
one more c++ questionquestion about volatile variable on multiple cores
Bihai,你就用atmoic完事了线程共享变量问题,搞不懂。
Volatile variables do not provide any atomicity (转载)How to use volatile in c++?
关于线程读写全局变量的问题java的同步问题请教
问个C++编译器如何处理函数内的static 变量Concurrency of assignment statement in C
相关话题的讨论汇总
话题: volatile话题: c++话题: 线程话题: barrier话题: quit