1. 程式人生 > >java並發編程的藝術,讀書筆記第三章

java並發編程的藝術,讀書筆記第三章

java並發編程的藝術

final域的內存語義

寫final域的重排規則:禁止把final域的寫重排序到構造方法之外,主要包括倆個個方面

1)JMM禁止編譯器把final域的寫重排序到構造方法之外

2)編譯器會在final域寫之後,構造函數return之前插入一個storestore屏障,這個屏障禁止處理器把final域的寫重排序到構造方法之外

寫final域的重排序規則可以確保:在對象引用為任意線程可見之前,對象的final域已經被

正確初始化過了,而普通域不具有這個保障

讀final域的重排規則:在一個線程中,初次讀對象引用與初次讀該對象包含的final域,JMM處理器禁止重排這兩個操作。編譯器會在讀final前插入loadload屏障

讀final域的重排序規則可以確保:在讀一個對象的final域之前,一定會先讀包含這個final

域的對象的引用

對復合final域的重排規則:

在構造函數內對一個final引用對象的成員域內的寫入,與隨後在構造函數外把這個構造對象的引用賦值給一個引用變量,這兩個操作之間不能重排序

雙重檢查鎖定與延遲初始化

基於volatile的解決方案

public class SafeDoubleCheckedLocking {

private volatile static Instance instance;

public static Instance getInstance() {

if (instance == null) {

synchronized (SafeDoubleCheckedLocking.class) {

if (instance == null)

instance = new Instance(); // instance為volatile,現在沒問題了

}

}

return instance;

}

}

基於類初始化的解決方案

JVM在類初始化階段(在class被加載後,且被線程使用前),會執行類的初始化。在執行類的初始化期間,JVM會獲取一個鎖,這個鎖可以同步多個線程對同一個類的初始化。

基於這個特性,可以實現另一種線程安全的延遲初始化方案

public class InstanceFactory {

private static class InstanceHolder {

public static Instance instance = new Instance();

}

public static Instance getInstance() {

return InstanceHolder.instance ;  // 這裏將導致InstanceHolder類被初始化

}

}

根據java規範,發生如下情況,會被立即初始化

1)T是一個類,而且一個T類型的實例被創建。

2)T是一個類,且T中聲明的一個靜態方法被調用。

3)T中聲明的一個靜態字段被賦值。

4)T中聲明的一個靜態字段被使用,而且這個字段不是一個常量字段。

5)T是一個頂級類(Top Level Class,見Java語言規範的§7.6),而且一個斷言語句嵌套在T

內部被執行。

類初始化的處理過程

類初始化的五個階段

1) 通過class對象上的同步(獲取class對象上的同步鎖) 來控制類或者接口的初始化,這個獲取鎖的線程會一直等待,直到當前線程獲取對象的初始化鎖

2) 線程執行類a的初始化,同時線程b在對應的初始化鎖的condition上等待

3)線程a設置狀態位intilized,並呼喚所有condition等待的線程喚醒

4)線程b結束類的初始化

5)線程c執行類的初始化


本文出自 “iter工作總結” 博客,請務必保留此出處http://5855156.blog.51cto.com/5845156/1954184

java並發編程的藝術,讀書筆記第三章