前言
併發程式設計的目的是讓程式跑的更快,但並不是啟動更多的執行緒,這個程式就跑的更快。有以下幾種挑戰。
挑戰及方案
上下文切換
單核CPU上執行多執行緒任務,通過給每個執行緒分配CPU時間片的方式來實現這個機制。時間片是CPU分配給每個執行緒執行的時間,時間片非常短,CPU通過不斷的切換執行緒執行,給我們人類留下的印象就是多個執行緒在同時執行。
由於執行緒有建立和上下文切換的開銷,當整個程式內部運算元不高的情況下,併發執行可能比序列執行來的慢。
儘可能降低上下文切換的次數,有助於提高併發效率。
- 無鎖併發程式設計。書中提到多執行緒競爭鎖時會發生上下文切換,所以竟可能避免使用鎖書中指的應該是為了競爭鎖而觸發的搶佔式上下文切換,因為日常多執行緒執行也需要上下文切換,可以通過不同執行緒處理不同分段的資料來降低。
- CAS演算法。Java中的Atomic包使用CAS演算法來更新資料,不需要加鎖CAS演算法目前還不是很瞭解
- 使用最少執行緒。
- 協程。協程,又稱微執行緒,纖程。英文名Coroutine。指的是在單執行緒裡面實現多工的排程之前在Python和Go裡面聽過這個概念,不過還沒做具體瞭解。
死鎖
併發程式設計中的另一挑戰是死鎖,會造成系統功能不可用。死鎖是指兩個或兩個以上的程式或者執行緒在執行過程中,由於競爭資源或者由於彼此通訊而造成的一種阻塞的現象。
避免死鎖的常見方法:
- 避免一個執行緒同時獲取多個鎖。
- 儘可能保證一個鎖內只佔有一個資源。
- 嘗試使用定時鎖。
資源限制的挑戰
比如說頻寬只有2Mb/s,你下載速度是1Mb/s,開10個執行緒速度也不會變成10Mb/s。書中提到在併發程式設計時需要考慮到資源上的限制。如果受制於資源,比如我資料庫連線數就10個,你每次用完都新建執行緒來做連線,整體程式的速度肯定會慢下來。
解決的方法有以下幾點:
- 對於硬體資源的限制,可以使用叢集來跑。
- 對於軟體資源上的限制,可以複用資源,比如複用資料庫連線。
根據資源的限制,靈活的去調整併發度。