- 问题概述:
a. Java内存模型规定了所有的变量都存储在主内存中。每条线程中还有自己的工作内存,不同工作内存间是不可见的,工作内存中保存了线程需要的变量,不同线程间变量的传递需要经过主内存才可以;
b. 普通的共享变量则无法保证可见性,因为不同线程在各自工作内存中更改变量值后,再重新写回主内存的时间是不确定的,再当其他线程读取主内存值时,也可能是原来的旧值;- 解决方法:
a. volatile关键字可以保证可见性,因为他会将主内存变量的更新通知到其他线程,是一种轻量级的锁;
b. CAS算法也可以保证可见性;
c. 通过synchronized和Lock也能够保证可见性,因为他们可以保证一个线程获取锁执行同步代码;
此次来讨论volatile关键字如何保持内存的可见性;
volatile 变量,用来确保将变量的更新操作通知到其他线程。
public class MyTest {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
new Thread(myRunnable).start();
while (true){
if (myRunnable.getFlag()) {
System.out.println("进来了");
break;
}
}
}
}
class MyRunnable implements Runnable{
boolean flag=false;
public boolean getFlag() {
return flag;
}
@Override
public void run() {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=true; //把flag的值设为true
System.out.println("线程将flag的值设为"+flag);
}
}
上述代码不能解决可见性问题,变量更新并没有通知到其他线程,即false更改为true后主线程并不能得到通知;执行结果如下:
使用关键字后:
class MyRunnable implements Runnable{
//volatile 可以解决内存可见性的问题 不用加锁
volatile boolean flag=false;
public boolean getFlag() {
return flag;
}
@Override
public void run() {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=true; //把flag的值设为true
System.out.println("线程将flag的值设为"+flag);
}
}
结果为: