编译器对代码的 reorder

原创 2011年01月09日 14:28:00

 

http://www.cs.umd.edu/users/pugh/java/memoryModel/jsr-133-faq.html#reordering

 

What is meant by 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. 

 

稍稍翻译下:


reordering 意味着什么

 

对 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依然会调整语句顺序。只是,同一个线程中,语句的调整,对单线程 没有任何影响;但是,这个调整产生的影响被其他线程看到了

 

相关文章推荐

Java-代碼混淆编译器

1.1 什么是Jocky?    我们知道,Java是一种跨平台的编程语言,其源码(.java文件)被编译成与平台无关的字节码(.class文件),然后在运行期动态链接。 这样,编译后的类文件中将包...
  • yqj234
  • yqj234
  • 2016年01月08日 14:05
  • 768

用java实现编译器之代码实现Thompson构造:在简单NFA的基础上构造更复杂的NFA

阅读博客的朋友可以到我的网易云课堂中,通过视频的方式查看代码的调试和执行过程:http://study.163.com/course/courseMain.htm?courseId=100283001...

C编译器剖析_5.3.1 中间代码生成及优化_If语句和复合语句的翻译

5.3.1   If语句和复合语句的翻译     我们先简单回顾一下对布尔表达式的翻译,我们通过调用TranslateBranch函数来产生跳转指令,从而实现布尔表达式的语义。在使用函数Transl...
  • SheIsC
  • SheIsC
  • 2015年04月20日 15:48
  • 751

深入浅出编译原理-6-一个完整的编译器前端的代码实现

引言    编译原理的学习是一个痛苦并快乐的过程 。 经过前面的内容,我们知道了,语言,语法,文法,产生式,推导,语法分析树,语素,词法单元,中间表示,等等等等,这些概念以及他们之间的区别和联系,...

编译器优化代码都干了些什么不为人知的事情?

首先介绍两个优化概念 常量传播           将编译期间可计算出结果的变量转换成常量,减少了变量的使用。            int main() { int nVar = 1; ...

Flex中的CSS: (1)本质:CSS被编译器转换为AS代码

进入正文前,我们先温习下什么是“CSS选择器”? CSS层叠样式表有很多种选择器,最基本的三种选择器:类选择器、类型选择器、ID选择器。 看几个例子:   (1-1)类选择器        ...
  • tiangej
  • tiangej
  • 2012年06月13日 11:16
  • 1039

java开发编译器之:LALR语法解析及代码生成

自顶向下的语法解析中,可以通过属性传递的方式去实现代码生成,属性传递的方式主要是在父函数调用子函数时,将属性作为参数进行传递。但是,就如上节我们看到的,LALR语法解析过程是通过栈而不是函数调用的方式...

powershell:脚本中检查mingw-w64编译器是否能生成 32/64位代码

mingw提供的编译器不同的版本生成代码的能力是不一样的,有的只能生成32位代码 有的只能生成64位代码,在powershell脚本中,为了自动化执行编译,就需要事先检查指定编译的生成代码的能力。 ...
  • 10km
  • 10km
  • 2017年06月21日 14:59
  • 316

语法文件解释器及编译器代码生成

1 文法文件的定义 语法文件使用的是LL分析方法。LL分析最简便的就是使用递归程序,或构造自动机。 WACC中,采取的硬编码的方式构造自动机。所谓硬编码,是与上章讲的按表格驱动实现自动机相对的。表格...

basic编译器代码

/** * * * * * * * * **///package JBasicShell;import java.io.*;// {{{ class JBasicShell/** * * * * * ...
  • wawa12
  • wawa12
  • 2011年03月03日 15:44
  • 94
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:编译器对代码的 reorder
举报原因:
原因补充:

(最多只允许输入30个字)