1. 程式人生 > >高併發程式設計-02-併發程式設計存在的風險

高併發程式設計-02-併發程式設計存在的風險

多執行緒的高併發程式設計提高了我們的CPU利用率及簡化開發模式,但是又同時給我們帶來了風險,使用不當就會有風險,那到底有什麼風險?我們來看看

1,執行緒的安全性問題

假設,我現在編寫了一個程式,來儲存系統的訪問量,如何實現呢?

很簡單,我可以設定一個全域性變數,然後,每次使用者訪問一次系統,我就自增1,那麼這個程式應該是這樣寫的,如下:

public class System {

    private int count;

    public int getCount(){

        return count++;

    }

}

這段程式碼,大家覺得有沒有問題?

如果在單執行緒的模式下,沒問題,但是在多執行緒的模式下,會有問題,為什麼?

因為其中一個關鍵的步驟,count++不是一個原子操作,這個操作實際會分為三個步驟,

分別是,讀取count值,給count值+1,將結果寫到count值上。

那麼大家想想,當我們有多個執行緒同時訪問這個資源的時候,會出現什麼情況?

這就是我們說的執行緒安全問題。

如果解決此類問題,java給我們提供一種同步機制,你只需要這麼做就可以解決問題:

public synchronized int getCount(){

    return count++;

}

好了,接下來,我們來說會出現的第二類問題

2,活躍性問題

比如,死鎖,飢餓,活鎖,這些都是屬於活躍性問題。當某個操作無法繼續執行時,這就是活躍性問題,我舉個死鎖的例子,比如我老婆跟我分工家務活,要求我先拖地,她就洗碗,而我要求她先洗碗,我再拖地,那麼這個時候,我們彼此手握對方進行下一步工作的開啟條件,但都彼此不願意先動手,於是就陷入了僵局,這就是死鎖。

換成程式的說法,就是A執行緒需要等待的鎖被B執行緒佔用,而B執行緒需要的等待的鎖被A執行緒佔用,所以相互都不釋放,於是就陷入了死鎖。

更多問題,我們後續繼續講解

3,效能問題

效能問題,你肯定會有疑問,多執行緒不就是為了提高系統的吞吐量嗎?怎麼還有效能問題?

這個原因很簡單,還是那句話,你沒有正確使用

下面我們來看看多執行緒可能帶來的效能問題有哪些?

當我們採用多執行緒程式設計時,每個執行緒會由CPU實現排程,分配一定的時間片,那這個時候,排程器就會頻繁掛起一個活躍的執行緒轉而執行另一個執行緒,這就是我們說的“上下文切換”,這種操作將會帶來極大的開銷。

還有一個問題,當CPU重新切換回之前活躍的執行緒時,執行緒是否要繼續之前未完成的操作,答案是必須的,那麼就需要做一件事,在CPU切換的時候,儲存執行緒的執行狀態,這又是一筆開銷。

最後,還有一種情況,就是多執行緒共享有狀態的資料時,需要使用同步機制來保證資料安全,而這些機制會抑制編譯器的某些優化,比如使得記憶體緩衝區中的資料失效等等,以及增加共享記憶體匯流排的同步流量

所以,有個重要的問題,一般我們的程式開啟多少執行緒合適?

當然不是越多越好,大家可以留言,說說你的答案