1. 程式人生 > >自圓其說併發程式設計之——認識執行緒開銷

自圓其說併發程式設計之——認識執行緒開銷

本系列博文,自圓其說之——聊聊併發,是希望自己在學習併發的過程中,建立起一套屬於自己的見解和知識體系,並能對其中的各種姿勢能自圓其說,做到知其言,並知其所以言。

首先,我們要學習併發程式設計的目的,是為了要讓程式跑得更加的快,但是在併發中,我們常常會面臨,cpu的上下文切換,死鎖,硬體和軟體資源的限制問題,我們應該如何應對這些難點呢?

上下文切換

上過作業系統的課,我們都知道在單核的cpu中,我們的作業系統在進行任務切換的時候,是需要時間的,cpu處理器是通過時間輪片來實現這個機制。
CPU通過時間片分配演算法來迴圈執行任務,當前任務執行一個時間片後會切換到下一個任務,但是,在切換前會儲存上一個任務狀態,以便下次切換回這個任務,在單核處理器中,併發其實也是序列執行,知識讓人感覺是並行處理罷了。

測試上下文切換次數和時長

    1. 使用Lmbench3 可以測量上下文切換的次數。
    1. 使用vmstat 可以測量上下文切換的次數。

如何減少上下文切換

減少上下文切換的方法有 (1)無鎖併發程式設計、(2) CAS演算法、(3)使用最少執行緒和使用協程。
* 無鎖併發程式設計。多執行緒競爭鎖時,會引起上下文的切換,所以多執行緒處理資料時,可以用一些辦法來避免使用鎖,如將資料的ID按照Hash演算法取模分段,不同的執行緒處理不同段的資料。
* CAS演算法。Java的Atomic包使用CAS演算法來更新資料,而不需要加鎖。
* 使用最少執行緒。避免建立不需要的執行緒,比如任務很少,但建立很多執行緒來處理,這樣會造成大量的執行緒都處於等待狀態。
* 協程:在單執行緒裡實現多工的排程,並在單執行緒裡維持多個任務間的切換

死鎖

現在我們介紹避免死鎖的幾個長見方法:
* 避免一個執行緒同時獲取對歌鎖。
* 避免一個執行緒在鎖內同時佔用多個資源,儘量保證每一鎖只是佔用一個資源。
* 嘗試使用定時鎖,使用lock.tryLock(timeout)來代替使用內部的鎖機制。
* 對於使用資料庫鎖,加鎖和解鎖必須在一個數據庫連線裡面,否則會出現解鎖失敗的情況。

public class DeadLockTest {

       private static String A = "A";
       private static String B = "B";

       public static
void main(String[] args) { new DeadLockTest().deadLock(); } private void deadLock() { Thread t1 = new Thread(new Runnable() { @Override public void run() { synchronized (A) { try { Thread.currentThread().sleep(1000); }catch(InterruptedException e) { e.printStackTrace(); } synchronized (B) { System.out.print("1"); } } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { synchronized (B) { try { Thread.currentThread().sleep(1000); }catch(InterruptedException e) { e.printStackTrace(); } synchronized (A) { System.out.print("1"); } } } }); } }

資源限制挑戰

1)資源限制是指在進行併發程式設計時,計算機執行的速度受限於計算機的硬體資源和軟體資源以及網路速度等。例如:伺服器的頻寬只有2Mb/s , 某個資源的下載速度是1Mb/s, 系統啟動10個執行緒下載,也不見的有多麼的快,速度也不會變成10Mb/s, 所以在進行併發程式設計的時候,要考慮這些資源限制。RPC的資料傳輸會受到頻寬的影響,硬碟讀寫速度和CPU的上下文的切換會受到處理器的效能影響。還有資料庫的連線數和socket連線數的影響等。
2)資源限制引發的問題
在併發程式設計中,將程式碼執行速度加快的原則是將程式碼的序列執行的部分變成併發執行。但是因為受限於資源,併發並不會加快,反而更加的慢,因為這樣就增加了cpu的上下文切換和任務排程的花銷了。
3)如何解決資源限制的問題
對於硬體資源的限制,可以考慮使用叢集的方式,這也是業界常用的方案。既然單機有資源的限制,那麼就在多機上執行。比如使用ODPS, Hadoop或者自己搭建伺服器叢集。不同的機器處理不同的資料。可以通過“資料ID%機器數”,計算出機器的編號,然後由這臺機器來處理這筆資料,常見的如訂單系統。
4)在資源限制的情況下進行併發程式設計
如何在資源限制地情況下,讓程式執行的更加的快速?那就要根據資源的限制,調整併發度。