第一章 走入並行世界(並行的基本概念)
本文摘自《實戰Java高併發程式設計》,瞭解詳細內容推薦購買原版書籍。
第一章 走入並行世界
1.1何去何從的平行計算
使用並行程式目的:1、獲得更好的效能。2、業務模型的需要,確實需要多個執行實體。
1.2基本的概念
1.2.1
同步(Synchronous):同步方法呼叫一旦開始,呼叫者必須等到方法呼叫返回後,才能繼續後續的行為。 非同步(Asynchronous):非同步方法一旦開始,方法呼叫就會立即返回,呼叫者就可以繼續後續的操作。而非同步方法通常會在另一個執行緒中“真實”的執行。整個過程,不會阻礙呼叫者工作。
1.2.2
併發(Concurrency):偏重於多個任務交替執行。 並行(Parallelism)
1.2.3
臨界區:表示一種公共資源或共享資料,可被多個執行緒使用。每次只能有一個執行緒使用,一旦資源被佔用,其他執行緒想用必須等待。
1.2.4
阻塞和非阻塞通常用來形容多執行緒間的相互影響。 阻塞(Blocking):一個執行緒佔用了臨界區資源,其他需要這個資源的執行緒需要在這個臨界區等待。等待導致執行緒被掛起,為阻塞。 非阻塞(Non-Blocking):相反,強調沒有一個執行緒可以妨礙其他執行緒執行。所有執行緒都會嘗試不斷向前執行。
1.2.5
死鎖、飢餓和活鎖都屬於多執行緒的活躍性問題。發生這幾種情況,可能相關執行緒不再活躍。 死鎖(Deadlock)
1.3併發級別
由於臨界區存在,多執行緒之間的併發必須受到控制。併發級別大致有:阻塞、無飢餓、無障礙、無鎖、無等待。
1.3.1
阻塞(Blocking):一個執行緒是阻塞的,那麼在其他執行緒釋放資源之前,當前執行緒無法繼續執行。當使用synchronized關鍵字,或重入鎖時,得到的就是阻塞的執行緒。 無論是synchronized關鍵字,或重入鎖,都會試圖在執行後續程式碼之前,得到臨界區的鎖,得不到執行緒就會被掛起等待,知道佔有所需資源。
1.3.2
無飢餓(Starvation-Free):如果鎖是公平的,飢餓就不會產生。
1.3.3
無障礙(Obstruction-Free):無障礙是一種最弱的非阻塞排程。執行緒如果無障礙執行,都可以進入臨界區。資料改壞進行回滾。(可以依賴“一致性標記”實現,執行緒操作之前讀取儲存標記,操作之後再讀取,檢查時候被修改過)
1.3.4
無鎖(Lock-Free):無鎖的並行都是無障礙的。無鎖情況下,所有執行緒都能嘗試對臨界區進行訪問,但是無鎖的併發保證必然有一個執行緒能在有限步數內完成操作離開臨界區。
1.3.5
無等待(Wait-Free):無鎖要求一個執行緒有限步數完成,無等待要求所有,這樣不會引起飢餓問題。 典型無等待機構RCU(Read-Copy-Update)。讀資料不控制,所有執行緒無等待,寫資料時,先去資料副本,修改副本,再合適時機回寫資料。
1.4並行的Amdahl定律、Gustafson定律
1.4.1
**Amdahl定律:**使用多核CPU對系統進行優化,優化效果取決於CPU數量以及系統中序列化程式比重。
1.5回到Java:JMM(Java記憶體模型)
JMM定義一種規則,保證多個執行緒間可以有效地、正確的協同工作。
1.5.1
原子性(Atomicity):指一個操作不可中斷的。其實多個執行緒一起執行,一個操作一旦開始,就不會被其他執行緒干擾。執行緒A賦值給i為1,執行緒B賦值i為2,原子性就是無論怎麼操作i只會是1或2。(long有64位,在32位系統中如果兩個執行緒同時寫入,對結果會有干擾)
1.5.2
可見性(Visibility):指一個執行緒修改了某個共享變數的值,其他執行緒是否能立即知道這個修改。 有序性(Ordering):原因是程式在執行時,可能會進行指令重排,重排後的指令與原指令順序未必一致。 指令執行步驟:
- 取指IF
- 譯碼和去暫存器運算元ID
- 執行或者有效地址計算EX
- 儲存器訪問MEM
- 寫回WB X表示中斷