volatile
代码实例
如下代码中,"Wow"是永远不会被打印出来的,因为所有的共享变量都存储于主内存,这里所说的变量指的是实例变量和类变量,不包含局部变量,因为局部变量是线程私有的,因此不存在竞争问题,flag
变量只在apple.start创建的线程中。
package com.klaus.thread;
public class VolatileTest {
public static void main(String[] args) {
Apple apple = new Apple();
apple.start();
while (true) {
// synchronized (apple){
if (apple.isFlag()) {
System.out.println("Wow");
}
// }
}
}
}
class Apple extends Thread {
private volatile boolean flag = false;
public boolean isFlag() {
return flag;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println("flag is " + flag);
}
}
可见性的解决方案
1.synchronized
因为某一个线程进入synchronized代码块前后,线程会获得锁,清空工作内存,从主内存拷贝共享变量最新的值到工作内存成为副本,执行代码,将修改后的副本的值刷新回主内存中,线程释放锁。
而获取不到锁的线程会阻塞等待,所以变量的值肯定一直都是最新的。
2.volatile
每个线程操作数据的时候会把数据从主内存读取到自己的工作内存,如果他操作了数据并且写了,其他已经读取的线程的变量副本就会失效了,需要都数据进行操作又要再次去主内存中读取了。
volatile保证不同线程对共享变量操作的可见性,也就是说一个线程修改了volatile修饰的变量,当修改写回主内存时,另外一个线程立即看到最新的值。
是不是看着加一个关键字很简单,但实际上他在背后含辛茹苦默默付出了不少,我从计算机层面的缓存一致性协议解释一下这些名词的意义。
源自https://mp.weixin.qq.com/s?__biz=MzAwNDA2OTM1Ng==&mid=2453142004&idx=1&sn=81ccddb6c8b37114c022c4ad50368ecf&scene=21#wechat_redirect
本文来自博客园,作者:klaus08,转载请注明原文链接:https://www.cnblogs.com/klaus08/p/15391262.html