指令重排序 as-if-serial

笔者认为看完一本书或刚要了解完一个知识点  最好自己先运行一些DEMO 自己尝试着去了解下各种意思  这样知识点最终一定是你的。靠死记硬背的讨论或简单的粗暴的看下资料 脑子里肯定还是一团浆糊。

public class FinalDemo {

 

// FinalDemo finalDemo;

// public final String b;

//

// public FinalDemo() {

// Random rw = new Random();

// int p = rw.nextInt(10);

// b="helloWorld"+p;

// }

//

// public void write() {

//

// finalDemo=new FinalDemo();

// }

 

public void doMethodParam( Product product) {

 

//String obj=b;

// Random rw = new Random();

// int p = rw.nextInt(10);

 

Product totalMoney=product;

System.out.println("线程:"+Thread.currentThread().getName()+"----money:"+totalMoney.getMoney() + "-----------before---" );

 

System.out.println("线程:"+Thread.currentThread().getName()+"----money"+totalMoney.getMoney() + "-----------end---" );

 

}

 

@Test

public void testFinalMethodParam() {

Thread[] thread=new Thread[4]; 

for(int i=0;i<4;i++) {

 

thread[i] = new Thread(new Runnable() {

 

@Override

public void run() {

int a=new Random().nextInt(10);

// TODO Auto-generated method stub

Product product=new Product();

product.setName("name_"+a);

product.setMoney("10"+a);

doMethodParam(product);

 

}

});

 

 

 

thread[i].start();

}

 

 

}

 

class Product{

 

private String name;

 

private String money;

 

public String getName() {

return name;

}

 

public void setName(String name) {

this.name = name;

}

 

public String getMoney() {

return money;

}

 

public void setMoney(String money) {

this.money = money;

}

 

 

}

 

}

 

打印结果:

线程:Thread-0----money:8-----------before---

线程:Thread-2----money:9-----------before---

线程:Thread-2----money9-----------end---

线程:Thread-0----money8-----------end---

线程:Thread-1----money:8-----------before---

线程:Thread-3----money:5-----------before---

线程:Thread-1----money8-----------end---

线程:Thread-3----money5-----------end---

 

从上述的打印结果  你看懂了什么。

总结如下:

1)上述中下行有两行before内容,并没有中规中矩的先before再end 说明了一个知识点:程序在执行过程中被指令重排序了。主要原因是编译器或处理器为了优化性能对指令序列进行排序的手段。

2)但是大家有没有观察到虽然表现为重排序 但同一个线程最终执行的结果是一样的,并不因为多线程的影响把值给改掉。这是因为JMM内存模型决定的。对于局部变量和方法参数都是线程私有的并不会被其他线程共享。

3)还有一点as-if-serial语义。不管怎么重排序 对于那种有依赖关系的单线程程序的执行结果不会被改变。处理器能保证对于有依赖关系的指令禁止重排序

原文地址:https://www.cnblogs.com/zhangfengshi/p/7086584.html