指令重排

[高并发Java 三] Java内存模型和线程安全

不想你离开。 提交于 2020-02-29 06:33:01
网上很多资料在描述Java内存模型的时候,都会介绍有一个主存,然后每个工作线程有自己的工作内存。数据在主存中会有一份,在工作内存中也有一份。工作内存和主存之间会有各种原子操作去进行同步。 下图来源于 这篇Blog 但是由于Java版本的不断演变,内存模型也进行了改变。本文只讲述Java内存模型的一些特性,无论是新的内存模型还是旧的内存模型,在明白了这些特性以后,看起来也会更加清晰。 1. 原子性 原子性是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其它线程干扰。 一般认为cpu的指令都是原子操作,但是我们写的代码就不一定是原子操作了。 比如说i++。这个操作不是原子操作,基本分为3个操作,读取i,进行+1,赋值给i。 假设有两个线程,当第一个线程读取i=1时,还没进行+1操作,切换到第二个线程,此时第二个线程也读取的是i=1。随后两个线程进行后续+1操作,再赋值回去以后,i不是3,而是2。显然数据出现了不一致性。 再比如在32位的JVM上面去读取64位的long型数值,也不是一个原子操作。当然32位JVM读取32位整数是一个原子操作。 2. 有序性 在并发时,程序的执行可能就会出现乱序。 计算机在执行代码时,不一定会按照程序的顺序来执行。 class OrderExample { int a = 0; boolean flag = false;