import javax.swing.text.html.StyleSheet;
import java.util.*;
public class Main{
private int x = 0;
private int y = 0;
private boolean flag = false;
public static void main(String[] args) throws InterruptedException{
Thread.currentThread().setName("线程A");
Main main = new Main();
Thread threadB = new Thread(main::writer,"线程B");
threadB.start();
System.out.println("x的值"+main.x);
System.out.println("Y的值"+main.y);
System.out.println("flag:"+main.flag);
System.out.println("线程结束");
}
public void writer(){
System.out.println("开始赋值操作");
this.x = 100;
this.y = 200;
this.flag = true;
}
}
就上述的代码而言,似乎没有太大的问题。我们启动了一个新的线程,新的线程会对x和y进行赋值。然后我们在赋值之后回到主线程,在主线程打印出x和y与flag的值。
但是我们尝试运行会发现:
D:\A-EssentialSoftWare\Java\jdk-17\bin\java.exe -Dvisualvm.id=52508452716600 "-javaagent:D:\A-EssentialSoftWare\All-Kinds-Of-IDE\IntelliJ IDEA 2024.1.2\lib\idea_rt.jar=58688:D:\A-EssentialSoftWare\All-Kinds-Of-IDE\IntelliJ IDEA 2024.1.2\bin" -Dfile.encoding=UTF-8 -classpath D:\A-ProgramingTask\JavaProgrammingTask\TestJavaSE\out\production\TestJavaSE Main
开始赋值操作
x的值0
Y的值200
flag:true
线程结束
这是为什么?
经过分析我们发现:
由于ThreadB与线程A是并行的关系。在ThreadB中发生了指令的重排序,y先被赋值。同时线程A在x赋值之前输出了四条System语句
那么解决策略是什么?
我们只要等线程B执行完之后,再让线程A继续运行即可
那怎么实现呢?
在线程A中 以线程B为主体调用join即可
import javax.swing.text.html.StyleSheet;
import java.util.*;
public class Main{
private int x = 0;
private int y = 0;
private boolean flag = false;
public static void main(String[] args) throws InterruptedException{
Thread.currentThread().setName("线程A");
Main main = new Main();
Thread threadB = new Thread(main::writer,"线程B");
threadB.start();
//下面的代码让threadB完全运行结束之后才会继续执行线程A的代码,相当于在线程B完成之前,线程A都是阻塞状态
//这样即使线程A发生了指令的重排序,也不会影响我们最终的输出结果
threadB.join();
System.out.println("x的值"+main.x);
System.out.println("Y的值"+main.y);
System.out.println("flag:"+main.flag);
System.out.println("线程结束");
}
public void writer(){
System.out.println("开始赋值操作");
this.x = 100;//这里发生了指令的重排序,先对y赋值,再对x赋值
this.y = 200;//倘若我们在y赋值之后,在x赋值之前。于主线程输出了四条输出语句,就会导致x=0的情况。
//因为x=100尚未执行 主线程就已经输出完了
//在这个例子中,我们通过threadB.join();避免了这一条,让线程B完成重排序后,线程A才能结束阻塞继续执行,从而解决了可见性问题
this.flag = true;
}
}