【Java多线程】Java内存模型与Volatile
2017-08-29 17:47
337 查看
1.Java内存模型
共享内存模型指的就是Java内存模型(简称JMM),JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(mainmemory)中,每个线程都有一个私有的本地内存(localmemory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。简单来说:程序开始运行,在主内存中有个共享变量,线程A和线程B需要用到共享变量,他们会各自从主内存中复制变量到属于线程自己的本地内存而不是直接操作主内存的共享变量,线程A和线程B对他们的复印出来的变量进行操作,如果没有及时的把新结果返回到主内存中共享,或者没有及时的从主内存中拿到新的共享变量,线程A和线程B在自己的本地内存中操作的复印变量就会发生误差,这也是造成并发线程安全问题的原因所在。
下面看个例子
TestVolatile.java
public class TestVolatile{ public static void main(String[] args) { VolatileThread thread = new VolatileThread(); Thread t = new Thread(thread); t.start(); try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } // 调用方法关闭线程 thread.stopThread(); } } class VolatileThread implements Runnable{ public static boolean flag = true; // 关闭线程的方法 public void stopThread() { flag = false; } @Override public void run() { System.out.println("线程开始执行"); while(flag){ } System.out.println("线程结束执行"); } }结果
可以看到,虽然调用了关闭方法,但是线程依然没有停止,好像无视flag=false继续运行。
在了解了JMM之后,可以知道虽然主内存里的共享全局变量flag改成了false,但是线程的本地内存里的flag依然是true,而循环是从线程的本地内存里取flag,所以不会停止。
2.Volatile
由于java内存模型会有主内存和线程本地内存不一致的问题,所以就有了volatile来修饰变量。由volatile修饰的全局变量,当值被改变时,会立刻更新到线程本地内存中。
// 用volatile修饰了静态全局变量 public static volatile boolean flag = true;结果
线程开始执行 线程结束执行现在已经能正确的执行了。
Q:那么volatile是不是能解决原子性问题呢?
A:volatile是非原子性的,看以下代码。
Test.java
public class Test { public static void main(String[] args) { TestThread thread = new TestThread(); Thread t1 = new Thread(thread); Thread t2 = new Thread(thread); // 启动两个线程操作 t1.start(); t2.start(); } } class TestThread implements Runnable { // 使用volatile修饰静态全局变量 public static volatile int count = 0; @Override public void run() { while (count < 100) { if(count < 100) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count++; System.out.println(count); } } } }结果片段
99 100 101
结果显然是不安全的,要想让线程安全,可以使用synchronized或者lock。
相关文章推荐
- Java多线程 -- 深入理解JMM(Java内存模型) --(四)volatile
- Java多线程-带你认识Java内存模型,内存分区,从原理剖析Volatile关键字
- Java多线程 -- 深入理解JMM(Java内存模型) --(四)volatile
- Java多线程 -- 深入理解JMM(Java内存模型) --(四)volatile
- 【Java多线程】-线程同步synchronized和volatile
- java多线程之内存可见性-synchronized、volatile
- java多线程中synchronized(同步块)和volatile的区别
- 13、Java并发性和多线程-Java Volatile关键字
- Java并发编程:volatile关键字解析(三.Java内存模型)
- Java多线程知识点整理(synchronized/volatile)
- JAVA多线程之volatile 与 synchronized 的比较
- Java多线程(二):线程同步synchronized和volatile
- Java之多线程内存可见性_2(volatile实现可见性)
- java多线程总结四:volatile、synchronized示例
- Java多线程系列八——volatile和ThreadLocal
- 彻底弄明白之java多线程中的volatile
- Java多线程 -- 深入理解JMM(Java内存模型) --(六)final
- Java多线程 -- 深入理解JMM(Java内存模型) --(三)顺序一致性
- Java多线程 -- 深入理解JMM(Java内存模型) --(一)基础
- Java多线程 -- 深入理解JMM(Java内存模型) --(六)final