Java内存模型
网上好多文章再讲到java内存模型时都讲方法区,堆栈等内容,我个人认为这属于jvm内存结构,我认为jmm指的是这个(如图)
当我们的类中存在共享变量(如全局静态变量)这些共享变量将放到java内存模型的主内存中去。
线程更改共享变量值过程
1.线程读取共享变量到自己的副本中
2.更改副本的值
3.刷新到主内存
线程间通讯
什么是线程间通讯
通俗的说就是当A线程将变量b的值更改了,线程B需要知道A将变量b改成了什么,线程B如何能够知道就是线程间如何通讯 。
线程间如何通讯
当线程A更改完成后,并且将更改后的值刷新到了主内存,线程B从主内存中读取了新值,这就完成了线程A,B间的通讯
线程不可见
当线程A将变量b的值更改之后还没来得及刷新到主内存,这时候CPU将执行权交给了线程B,线程B拿着线程A修改之前的变量b去做相应的操作,可能运行的结果并不是你所要的,这就叫做线程不可见性
不可见例子
(这个例子比较容易演示出线程安全问题)
package com.demo.thread;
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(new ThreadA());
threadA.start();
Thread.sleep(100);
ThreadA.flag = false;
System.out.println("flag已设为false");
}
}
/**
* 线程A
* @author Administrator
*
*/
class ThreadA implements Runnable{
public static boolean flag = true;
@Override
public void run() {
while(flag) {
}
System.out.println("线程A结束");
}
}
运行结果
原因:主线程将flag设为false之后,由于jvm优化原因线程A仍读取的是自己的副本,所以一直在做while循环
解决办法
public volatile static boolean flag = true;**加粗样式**
在flag前加volatile关键字,这样线程读取时,会强制从主内存中读取
结果