在java中,设计之初就有了:主内存、线程工作内存,所以其实每一个线程执行时,都是将主线程copy一份到工作线程,执行修改后,再同步回去。
所以,就有四组内存操作方式:
1、读主内存,加载到工作内存
2、 通过执行引擎使用工作内存数据、修改工作内存
3、读工作内存、写到主内存
4、使用内存时会:加锁,解锁
volatile可以让多个线程可见,或者说不再操作工作内存
package com.quxiao.controller;import java.sql.Time; import java.util.ArrayList; import java.util.Random; import java.util.concurrent.*; import java.util.stream.LongStream;/*** @program: package1* @author: quxiao* @create: 2023-09-27 15:22**/ public class t3 {static volatile int sum = 0;public static void main(String[] args) throws InterruptedException {new Thread(() -> {while (sum == 0) {}System.out.println(1);}).start();TimeUnit.SECONDS.sleep(1);sum = 1;} }
但是使用了volatile就没有了原子性,也就是线程操作不再唯一,例如:
A线程取出时为10,正准备+10,数据变成了15,结果就成了15+10。
指令重排(很神奇的一个东西):
package com.quxiao.controller;import java.sql.Time; import java.util.ArrayList; import java.util.Random; import java.util.concurrent.*; import java.util.stream.LongStream;/*** @program: package1* @author: quxiao* @create: 2023-09-27 15:22**/ public class t3 {static int x = 0;static int y = 0;static int a = 0;static int b = 0;public static void main(String[] args) throws InterruptedException {//大致如此,但是new Thread(() -> {x = a;b = 1;}).start();new Thread(() -> {y = b;a = 2;}).start();//有可能x=2,y=1System.out.println(x + ":" + y);} }
x=b和a=1这两句话完全没有关联,编译器就有可能把他俩重新排顺序。(上面的代码只是理论,其实很难遇到)
加上volatile,就能解决,多了两层内存屏障: