指令重排序 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語義。不管怎麽重排序 對於那種有依賴關系的單線程程序的執行結果不會被改變。處理器能保證對於有依賴關系的指令禁止重排序
指令重排序 as-if-serial