模拟一个内存不可见导致的问题
volatile 关键字:当多个线程进行操作共享数据时,可以保证内存中的数据可见。
相较于 synchronized 是一种较为轻量级的同步策略。
1. volatile 不具备“互斥性”
2. volatile 不能保证变量的“原子性”
package com.fjf.juc;
/**
* 2018年7月20日 19:36:23
* @author fjf
*
* volatile 关键字
*
* 模拟一个因为内存不可见导致的问题
*
*/
public class TestVolatile {
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo();
new Thread(td).start();
//ThreadDemo2 td2 = new ThreadDemo2();
//td2.start();
while(true){ //主要原因是while(true)的执行效率高,偏底层。main都来及去主线程中去同步
/* try {
//Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
//if(true){
//System.out.println(Thread.currentThread().getName());
if(td.isFlag()){
System.out.println("----------*****-------");
break;
}
}
}
}
//线程类 实现runable接口
class ThreadDemo implements Runnable{
//private volatile boolean flag = false;
private boolean flag = false;
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName());
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println("flag="+flag);
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
//继承Thread类 来创建多线程
class ThreadDemo2 extends Thread{
private boolean flag = false;
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println("flag="+flag);
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
没有volatile时,线程thread-0 把flag变成true,但是main线程中if(td.isflag())一直还是false,导致“——*—–”输不出来,程序无法结束。*
加上volatile后,thread-0修改flag后,main可以获取到,程序输出,结束。
设计的思路:
1.共享变量flag;
2.thread-0线程去写(修改),main线程去读。而且先thread-0 sleep会,让main读走旧值
3.while(true)的效率特别高,main线程都无法同步主存。