天天看點

Java并發程式設計藝術筆記

第二章 Java 并發機制的底層實作原理

1.volatile是輕量級的sychronized,保證了共享變量的可見性。可見性的意思是當一個線程修改一個共享變量的時候,另外一個線程能讀到這個修改的值。

volatile instance = new Singleton()

轉成彙編代碼,如下

0x01a3de1d: movb 0x0,0x1104800( 0x0, (%)

2.Java 語言規範第三版對volatile的定義如下:Java程式設計語言允許線程通路共享變量,為了確定共享變量能被準确和一緻地更新,線程應該確定通過排他鎖��單獨獲得這個變量。

3.volatile 的兩條實作原則

1)Lock字首指令會引起處理器緩存回寫到記憶體。

2)一個處理器的緩存回寫到記憶體會導緻其它處理器的緩存無效

3)volatile的使用優化,Java并發程式設計大師Doug lea的JDK7的并發包裡新增一個隊列集合類LinkedTransferQueue,它在使用volatile變量時,用一種追加位元組的方式來優化隊列處隊和入隊的性能。Doug lea使用追加64位元組的方式來填滿告訴緩沖區的緩存行,避免頭尾節點加載到同一個緩存行,使2個節點的修改不會互相鎖定。

4.sychronized的實作原理與應用

1)重量級鎖,Java SE1.6為了減少獲得鎖和釋放鎖帶來的性能消耗而引入的偏向鎖和輕量級鎖,以及鎖的存儲結構和更新過程。

2)JVM基于進入和退出Monitor對象來實作方法同步和代碼塊同步,但兩者的實作細節不一樣。代碼塊同步是使用monitorenter和monitorexit指令實作的,而方法同步則是使用另外一種方式實作的。

5.鎖的更新與對比

HotSpot的作者經過研究發現,大多數情況下,鎖不僅不存在多線程競争,而且總是由同一個線程多次獲得,為了讓線程獲得鎖的代價更低而引入了偏向鎖。

輕量級鎖使用CAS自旋來擷取鎖。

重量級鎖,線程阻塞來競争鎖。

第三章 Java記憶體模型

JVM的邏輯記憶體模型

Java并發程式設計藝術筆記

1)程式計數器(Program Counter Register)是一塊較小的記憶體空間,它的作用可以看

做是目前線程所執行的位元組碼的行号訓示器,每條線程都需要有一個獨立的程式計數器,各條線程之間的計數器互不影響,獨立存儲。

Happens-before是JMM最核心的概念。

第四章 Java并發程式設計基礎

1.線程優先級不能作為程式正确性的依賴,因為作業系統可以完全不用理會java對于線程優先級的設定。

2.中斷可以了解為線程的一個辨別位屬性,它表示一個運作中的線程是否被其它線程進行了中斷操作。中斷好比其它線程對該線程打了個招呼,其它線程通過該線程的interrupt()方法對其進行中斷操作。isInterrupted()可以用來進行判斷是否被中斷,也可以調用靜态方法Thread.interrupted()對目前線程的中斷辨別位進行複位。mark:如果該線程處于終結狀态,即使該線程被中斷過,isInterrupted()依然傳回false。

3.volatile保證線程的可見性,sychronized保證線程的可見性及排它性。

4.管道輸入/輸出流,它主要用于線程之間的資料傳輸,而傳輸的媒介為内在。

第五章 Java中的鎖

1.Lock接口與sychronized的不同,失去了隐式擷取與釋放鎖的便利,卻擁有了擷取與釋放鎖的靈活性,可操作性,可中斷及逾時的擷取鎖。

2.隊列同步器AbstractQueuedSychronizer,是用來建構鎖或者其它同步元件的基礎架構

1)使用int成員變量表示同步狀态

2)通過内置的FIFO隊列來完成資源擷取線程的排隊工作

3)使用方式是繼承,實作其抽象方法來管理同步狀态,通過getState,setState,compareAndSetState原子性的改變同步狀态

4)子類被推薦作為自定義同步元件的靜态内部類,同步器本身不實作任何同步接口,僅僅定義了若幹同步狀态擷取和釋放的方法來供自定義同步元件使用

3.同步器是鎖實作的關鍵,在鎖的實作中聚合同步器,利用同步器來實作鎖的語義。可以這樣了解二者的關系:鎖是面向使用者的,它定義了使用者與鎖互動的接口,隐藏了實作細節,同步器面向的是鎖實作者,它簡化了鎖的實作方式,屏蔽了同步狀态管理,線程排隊,等待與喚醒等底層操作。鎖和同步器很好的隔離了使用者和實作者所需要關注的領域。

4.同步器的設計是基于模闆方法模式的,也就是說,使用者需要繼承同步器并重寫指定的方法。

5.隊列同步器的實作分析

1)同步隊列,一個FIFO雙向隊列,目前線程擷取同步狀态失敗時,同步器會将目前線程以及等待狀态等資訊構造成一個節點Node并将其加入同步隊列,同時阻塞目前線程,當同步狀态釋放時,會把首節點中的線程喚醒,使其再次嘗試擷取同步狀态

2)Node:

Java并發程式設計藝術筆記

waitStatus:等待狀态,

CANCELLED:1(由于在同步隊列中等待的線程等待逾時或者被中斷),需要從同步隊列中取消等待,節點進入該狀态将不會變化

SIGNAL:值為-1,後繼節點的線程處于等待狀态,而目前節點的線程如果釋放了同步狀态或者被取消,将會通知後繼節點,使後繼節點的線程得以運作

CONDITION:值為-2,節點在等待隊列中,節點等待在Condition上,當其它線程對Condition調用了signal()方法後,該節點将會從等待隊列中轉移到同步隊列中,加入到對同步狀态擷取中

PROPAGATE:值為-3,表示下一次共享式同步狀态将會無條件地被傳播下去

prev:前驅節點,當節點加入同步隊列時被設定(尾部添加)

next:後繼節點

nextWaiter:等待隊列中的後繼節點。如果目前節點是共享的,那麼這個字段将是一個SHARED常量,也就是說節點類型(獨占與共享)和等待隊列中的後繼節點共用同一個字段

6.重入鎖,支援重進入的鎖,表示該鎖能夠支援一個線程對資源的重複加鎖,另外可支援公平與非公平2種選擇,另外sychronized隐匿支援重進入

1)實作可重入

線程再次擷取鎖:鎖需要去識别擷取鎖的線程是否為目前持有鎖的線程,如果是,則再次成功擷取;

鎖的最終釋放:線程N次擷取鎖,随後在第N次釋放了鎖,其它線程能夠擷取到鎖,鎖的最終釋放需要鎖對于擷取進行自增,計數表示目前鎖被重複擷取的次數,而鎖被釋放時,計數自減,當計數為0時表示鎖被成功釋放

非公平鎖可以減少線程的切換

7.讀寫鎖

1)讀寫鎖的實作分析

讀寫狀态的設計:一個整型變量,高16位表示讀,低16位表示寫,假設目前狀态為S,寫狀态等于S&0x0000FFFF(将高16位抹去),讀狀态等于S>>>16(無符号右移16位)

寫狀态+1:S+1

讀狀态+1:S+(1<<16),也就是S+0x00010000

2)鎖降級:寫鎖降級為讀鎖,把持住寫鎖,再擷取讀鎖,随後釋放寫鎖

8.LockSupport工具,阻塞與喚醒線程

9.Condition類似Object螢幕

Java并發程式設計藝術筆記