指令重排序对多线程的影响

指令重排序

对单线程程序执行结果没有影响、虚拟机为优化和提升性能而对指令进行的一种重排序。例如:

int a,b,c=0;
a = 1;
b = 1;
c = a+b;

&

int a,b,c=0;
b = 1;
a = 1;
c = a+b;

结果是一样的。

但如果是在多线程中,em…,假设有一个加法:
假设有boolean flag = false;int a,b=0;

public  int plus(){
	if(flag == false){
	a = 1;
	b = 1;
 	flag = true;//说明a,b已经赋值
	}
	return a+b;
}

现在假定有A、B两个线程同时调用plus()方法。

注意:

在if块儿中,三个赋值操作可以交换,因为不影响最终的结果(对单线程来说),假设过程如下:

线程A 线程B
flag==false
a=1
flag = true a+b
b=1
a+b
结果为2 结果为1

这显然违背了指令重排序的初衷,说明其在多线程中不适用。大家以后写多线程一定要注意这个问题。

单例模式中的DCL(double checked locking)

public class DCL{
 private static DCL s;
 private DCL(){
  
 }
 public static  DCL getInstance() {
  if(s==null) {
   DCL sl;
   synchronized(DCL.class) {
    sl = s;
    if(sl == null) {
     synchronized(DCL.class) {
      if(sl == null) 
      sl = new DCL();
     }
     s = sl;
    }
   }
  }
  return s;
 }
}

这是修订过够的DCL,getInstance()方法中尝试引入第二个DCL变量以及第二次加锁解决指令重排序带来的问题。但注意在第二个if块儿中,同步语句块和赋值语句s = sl仍然存在指令重排序问题(这里可能是,同步块儿可以确保创建新DCL变量连续地完成,但s=sl这个赋值动作和同步块儿是平行的)。

也可以在方法名前使用volatile关键字禁止重排序。

发布了2 篇原创文章 · 获赞 4 · 访问量 119

猜你喜欢

转载自blog.csdn.net/weixin_44883515/article/details/104323946