JVM的重排序 - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 技术分享 >

JVM的重排序

发表时间:2020-10-19

发布人:葵宇科技

浏览次数:21


重排序平日是编译器或运行时情况为了优化法度榜样机能而采取的对指令进行从新排序履行的一种手段。重排序分为两类:编译期重排序和运行期重排序,分别对应编译时和运行时情况。
在并发法度榜样中,法度榜样员会特别存眷不合过程或线程之间的数据同步,特别是多个线程同时修改同一变量时,必须采取靠得住的同步或其它办法保障数据被精确地修改,这里的一条重要原则是:不要假设指令履行的次序,你无法预知不合线程之间的指令会以何种次序履行。
然则在单线程法度榜样中,平日我们轻易假设指令是次序履行的,不然可以想象法度榜样会产生什么恐怖的变更。幻想的模型是:复荡蚋令履行的次序是独一且有序的,这个次序就是它们被编写在代码中的次序,与处理器或其它身分无关,这种模型被称作次序一致性模型,也是基于冯·诺依曼体系的模型。当然,这种假设本身是合理的,在实践中也鲜有异常产生,但事实上,没有哪个现代多处理器架构会采取这种模型,因为它是在是太低效了。而在编译优化和CPU流水线中,几乎都涉及到指令重排序。

编译期重排序


编译期重排序的典范就是经由过程调剂指令次序,在不改变法度榜样语义的前提下,尽可能削减存放器的攫取、存储次数,充分复竽暌姑存放器的存储值。
假设第一条指令计算一个值赋给变量A并存放在存放器中,第二条指令与A无关但须要占用存放器(假设它将占用A地点的那个存放器),第三条指令应用A的值且与第二条指令无关。那么如不雅按照次序一致性模型,A在第一条指令履行过后被放入存放器,在第二条指令履行时A不再存在,第三条指令履行时A从新被读入存放器,而这个过程中,A的值没有产生变更。平日编译器都邑交换第二和第三条指令的地位,如许第一条指令停止时A存在于存放器中,接下来可以直接大年夜存放器中攫取A的值,降低了反复攫取的开销。

重排序对于流水线的意义


现代CPU几乎都采取流水线机制加快指令的处理速度,一般来说,一条指令须要若干个CPU时钟周期处理,而经由过程流水线并行履行,可以在一致的时钟周期内履行若干条指令,具体做法简单地说就是把指令分为不合的履行周期,例如攫取、寻址、解析、履行等步调,并放在不合的元件中处理,同时在履行单位EU中,功能单位被分为不合的元件,例如加法元件、乘法元件、加载元件、存储元件等,可以进一步实现不合的计算并行履行。
流水线架构决定了指令应当被并行履行,而不是在次序化模型中所认为的那样。重排序有利于充分应用流水线,进而达到超标量的效不雅。

确保次序性


尽管指令在履行时并不必定按照我们所编写的次序履行,但毋庸置疑的是,在单线程情况下,指令履行的最终效不雅应当与其在次序履行下的效不雅一致,不然这种优化便会掉去意义。
平日无论是在编译期照样运行期进行的指令重排序,都邑知足膳绫擎的原则。

Java存储模型中的重排序


在Java存储模型(Java Memory Model, JMM)中,重排序是十分重要的一节,特别是在并发编程中。JMM经由过程happens-before轨则包管次序履行语义,如不雅想要让履行操作B的线程不雅察到履行操作A的线程的结不雅,那么A和B就必须知足happens-before原则,不然,JVM可以对它们进行随便率性排序以进步法度榜样机能。
volatile关键字可以包管变量的可见性,因为对volatile的操作都在Main Memory中,而Main Memory是被所有线程所共享的,这里的价值就是就义了机能,无法应用存放器或Cache,因为它们都不是全局的,无法包管可见性,可能产生脏读。
volatile还有一个感化就是局部阻拦重排序的产生,对volatile变量的操作指令都不会被重排序,因为如不雅重排序,又可能产生可见性问题。
在包管可见性方面,锁(包含显式锁、对象锁)以及对原子变量的读写都可以确保变量的可见性。然则实现方法略有不合,例如同步锁包管获得锁时大年夜内存里从新读入数据刷新缓存,释放锁时将数据写回内存以保数据可见,而volatile变量干脆都是读写内存。

相关案例查看更多