Java内存模型——JMM

2018/10/20 Java

Java JMM 内存模型是围绕并发编程中原子性、可见性、有序性三个特征来建立的,关于原子性、可见性、有序性的理解如下:

  • 原子性:就是说一个操作不能被打断,要么执行完要么不执行,类似事务操作,Java 基本类型数据的访问大都是原子操作,long 和 double 类型是 64 位,在 32 位 JVM 中会将 64 位数据的读写操作分成两次 32 位来处理,所以 long 和 double 在 32 位 JVM 中是非原子操作,也就是说在并发访问时是线程非安全的,要想保证原子性就得对访问该数据的地方进行同步操作,譬如 synchronized 等。

  • 可见性:就是说当一个线程对共享变量做了修改后其他线程可以立即感知到该共享变量的改变,从 Java 内存模型我们就能看出来多线程访问共享变量都要经过线程工作内存到主存的复制和主存到线程工作内存的复制操作,所以普通共享变量就无法保证可见性了;Java 提供了 volatile 修饰符来保证变量的可见性,每次使用 volatile 变量都会主动从主存中刷新,除此之外 synchronized、Lock、final 都可以保证变量的可见性。

  • 有序性:就是说 Java 内存模型中的指令重排不会影响单线程的执行顺序,但是会影响多线程并发执行的正确性,所以在并发中我们必须要想办法保证并发代码的有序性;在 Java 里可以通过 volatile 关键字保证一定的有序性,还可以通过 synchronized、Lock 来保证有序性,因为 synchronized、Lock 保证了每一时刻只有一个线程执行同步代码相当于单线程执行,所以自然不会有有序性的问题;除此之外 Java 内存模型通过 happens-before 原则如果能推导出来两个操作的执行顺序就能先天保证有序性,否则无法保证,关于 happens-before 原则可以查阅相关资料。

所以说如果想让 Java 并发程序正确的执行必须保证原子性、有序性、可见性,只要三者中有任意一个不满足并发都无法正确执行。

想留言却没看到评论框?点这里。

Search

    Post Directory