作用:volatile这个关键字主要是保证各个线程的数据的强一致性
说到数据的强一致性首先要清楚各个线程的数据是怎么来的。
首先主内存中会有一份数据,然后开启线程之后会向缓存中取数据,如果缓存中没有则向主内存中取数据并放入缓存中。
这样就会出现线程1修改了缓存中tmp的值,然而线程2中tmp的值依旧没有发生改变,volatile关键字就主要用于解决这个问题。
public class VolatileDemo extends Thread {
int tmp = 0;
int i=0;
public void run() {
while(tmp==0){
i++;
}
}
public static void main(String[] args) throws Exception{
VolatileDemo t1 = new VolatileDemo();
t1.start();
Thread.sleep(1000);
t1.tmp++;
System.out.println("fin"+t1.i);
}
}
这种情况就是子线程t1中的tmp缓存没有改变,所以运行之后会发现程序一直不会结束,当然,如果在子线程中加入输出语句就会结束。
public class VolatileDemo extends Thread {
int tmp = 0;
int i=0;
public void run() {
while(tmp==0){
i++;
System.out.println(i);
}
}
public static void main(String[] args) throws Exception{
VolatileDemo t1 = new VolatileDemo();
t1.start();
Thread.sleep(1000);
t1.tmp++;
System.out.println("fin"+t1.i);
}
}
我看了下别的文章,是由于输出的时候都会清除工作内存去同步主内存,所以这时候子线程缓存中的tmp同步了主内存变成了1结束了。
那么如果不使用输出使用volatile关键字就会强制去主内存读取,而不使用缓存。
public class VolatileDemo extends Thread {
volatile int tmp = 0;
int i=0;
public void run() {
while(tmp==0){
i++;
}
}
public static void main(String[] args) throws Exception{
VolatileDemo t1 = new VolatileDemo();
t1.start();
Thread.sleep(1000);
t1.tmp++;
System.out.println("fin"+t1.i);
}
}
总结:volatile实际上就是多线程中保证数据强一致性,实际原理就是在线程读取修改数据时不使用缓存,去主内存中读取修改值。
参考:
Java并发编程学习笔记 深入理解volatile关键字的作用 https://www.cnblogs.com/daxin/p/3364014.html
System.out.println对线程安全的影响 https://blog.csdn.net/ft305977550/article/details/78769573