一、代码示例
package cn.edu.tju.handler;
public class ReorderingTest {
private static boolean stopFlag=false;
private static int counter=0;
private static int x=0;
private static int y=0;
private static int a=0;
private static int b=0;
public static void main(String[] args) throws Exception{
while(stopFlag!=true){
x=0;y=0;
a=0;b=0;
Thread thread1=new Thread(new Runnable() {
@Override
public void run() {
a=1;
x=b;
}
});
Thread thread2=new Thread(new Runnable() {
@Override
public void run() {
b=1;
y=a;
}
});
thread1.start();
thread2.start();
counter++;
thread1.join();
thread2.join();
if(x==0&&y==0){
System.out.println("第"+counter+"组线程的修改之后x=0且y=0");
break;
}
}
System.out.println("程序即将退出...");
}
}
程序运行一段时间之后输出:
二、分析:何谓指令重排序?也就是cpu在保证单线程执行某段代码时能保证执行结果不变的前提下,对代码的执行顺序做调整。例如线程thread1的run()方法中的代码:
a=1;
x=b;
当单个线程执行这两句代码时,将两条语句的执行顺序互换即
x=b;
a=1;
这样也不会影响最终的执行结果。CPU就有可能按照调整顺序后的代码顺序进行执行。
同理,thread2的run()方法的代码
b=1;
y=a;
也可能重排序为如下执行顺序
y=a;
b=1;
但是,在thread1和thread2多个线程同时运行的情况下,这种指令重排序就会造成最终结果的不确定性。为了防止指令重排序的发生,需要给定义的变量加volatile关键字来修饰。
上述例子,只有在thread1的执行顺序为:
x=b;
a=1;
且thread2的执行顺序为:
y=a,
b=1;
时才会出现x=0且y=0的结果