開坑!從今天起開始看《並發編程的藝術》,這本書是經過學長的推薦才得知的,正好能讓我對並發編程有更深入的了解。其實項目中已經開始遇到並發問題了,但是這方面一直沒有得到系統的學習。現在忙裡偷閒,趕緊補上。
PS: 特意找了一張和鎖相關的圖片,同時也寓意著精誠所至,金鎖為開🔒
一、上下文切換#
即使是單核處理器也支持多線程執行代碼,CPU 通過給每個線程分配 CPU 時間片(一般為幾十毫秒)實現這個機制。
當前任務執行一個時間片後會切換到下一個任務。在切換前會保存上一個任務的狀態,以便下次
切換回這個任務時,可以再加載這個任務的狀態。任務從保存到再加載的過程就是一次上下文切換。
如何減少上下文切換?
- 無鎖並發編程。多線程競爭鎖時,會引起上下文切換,可以用一些辦法避免使用鎖,如將數據的 id 取模分段,不同的線程處理不同段的數據
- CAS 算法:Java 的 Atomic 包使用 CAS 算法來更新數據,不需要加鎖
- 使用最少線程,避免創建不需要的線程
- 在單線程裡實現多任務的調度,並在單線程裡維持多個任務間的切換
二、死鎖#
避免死鎖的幾個常見方法:
- 避免一個線程獲取多個鎖
- 避免一個線程在鎖內同時佔用多個資源,盡量保證每個鎖只佔用一個資源
- 嘗試使用定時鎖,使用 lock.tryLock (timeout) 來替代使用內部鎖機制
- 對於數據庫鎖,加鎖和解鎖必須在一個數據庫連接裡,否則會出現解鎖失敗的情況
三、資源限制的挑戰#
問題:如果將某段串行的代碼並發執行,因為受限於資源,仍然在串行執行,這時候程序不僅不會加快執行,
反而會更慢,因為增加了上下文切換和資源調度的時間。
如何解決:
對於硬件資源的限制,使用機群並行執行程序,通過搭建伺服器集群,不同的機器處理不同的數據
對於軟件資源的限制,可以考慮使用資源池將資源複用
根據不同的資源限制調整程序的並發度