http://www.cs.umd.edu/users/pugh/java/memoryModel/jsr-133-faq.html#reordering
There are a number of cases in which accesses to program variables (object instance fields, class static fields, and array elements) may appear to execute in a different order than was specified by the program. The compiler is free to take liberties with the ordering of instructions in the name of optimization. Processors may execute instructions out of order under certain circumstances. Data may be moved between registers, processor caches, and main memory in different order than specified by the program.
For example, if a thread writes to field a and then to field b, and the value of b does not depend on the value of a, then the compiler is free to reorder these operations, and the cache is free to flush b to main memory before a. There are a number of potential sources of reordering, such as the compiler, the JIT, and the cache.
The compiler, runtime, and hardware are supposed to conspire to create the illusion of as-if-serial semantics, which means that in a single-threaded program, the program should not be able to observe the effects of reorderings. However, reorderings can come into play in incorrectly synchronized multithreaded programs, where one thread is able to observe the effects of other threads, and may be able to detect that variable accesses become visible to other threads in a different order than executed or specified in the program.
Most of the time, one thread doesn't care what the other is doing. But when it does, that's what synchronization is for.
稍稍翻译下:
对 variable(instance field, class field, or component of array,绝不包括method parameter, local variable) 的访问并不按程序指定的顺序进行,而是以其他不同顺序执行,这种情形,在很多情况下都会出现1、编译器可以以优化的形式自由的 reordering 程序指令。2、处理器在某些情况下会打乱程序指令顺序来执行(提高执行速度,当然,在保证程序正确前提下)。3、寄存器、处理器缓存以及内存之间 的数据移动可能也会以和程序所指定的顺序 不同的顺序来执行
例如,某个线程写入 field a,然后写入 field b,并且 b 的值不会依赖于 a 的值,此时,a)、编译器可以自由的 reordering 这些指令,b)、缓存也可以先于 a 将 b 的值刷新到内存c)、很多潜在的因素都会影响到 重排序,比如,编译器,JIT以及cache
编译器、运行时环境、硬件都被期望来产生 “貌似顺序化操作”的语义(create the illusion of as-if-serial semantics),也就是说,在单线程环境中,程序不应该看到 reordering 所产生的影响。
但是,在未能正确同步的多线程程序中,reordering 的影响就凸显出来了,这种情况下
a)、一个线程可以看到另一个线程的 reordering 所产生的影响
b)、一个线程可能会发觉 自己对变量的访问对另一个线程可见,但是,这个可见不是以 真正执行的或者程序所指定 的顺序,而是以其他不同的顺序所可见的
多数情况下,一个线程并不会关心其他线程在做什么(这里的“做什么”就是指对variable做了何种操作。因为线程间不能进行交互,他们的沟通仅仅在于操作同一个variable)。但是,如果使用了synchronized,此线程就会关心“其他线程对vairable做了什么”
看其他资料时产生的疑问
http://www.javaeye.com/topic/260515/
同一个线程执行上面的两个操作,操作A:x = 3和操作B:y = 2。根据单线程规则,操作A
happen-before操作B,但是操作A却不一定在时间上先于操作B发生,这是因为编译器的重新排
序等原因,操作B可能在时间上后于操作B发生。这个例子也说明了,分析操作上先后顺序是多
么地不靠谱,它可能完全违反直观感觉。
我的理解:
1、如果我认为:“即使在同一个线程中,依然存在compiler调整语句的顺序”
2、如果我认为:“调整语句顺序,仅仅是‘在其他线程看来,调整了顺序’(因为其他线程看到
后面的操作有正确值了,前面的操作却还没有,即 后面的操作在main memory中看到了,但是,前面的操作在main memory中却还看不到)”
结论就是:即使同一个线程中,compiler依然会调整语句顺序。只是,同一个线程中,语句的调整,对单线程 没有任何影响;但是,这个调整产生的影响被其他线程看到了