1. 程式人生 > >高並發編程-03-並發編程存在的風險

高並發編程-03-並發編程存在的風險

private 共享內存 等待 結果 模式 image auto 總線 開發

多線程的高並發編程提高了我們的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切換的時候,保存線程的執行狀態,這又是一筆開銷。

最後,還有一種情況,就是多線程共享有狀態的數據時,需要使用同步機制來保證數據安全,而這些機制會抑制編譯器的某些優化,比如使得內存緩沖區中的數據失效等等,以及增加共享內存總線的同步流量

所以,有個重要的問題,一般我們的程序開啟多少線程合適?

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


高並發編程-03-並發編程存在的風險