做並發編程的時候需要注意哪些事項呢。 上下文開銷
CPU的線程是通過調度演算法分配不同的時間片,當一條線程的時間片用完後,作業系統會暫停該線程,並儲存該線程相應的資訊,然後再隨機播放一條新線程去執行,這個過程就稱為“線程的環境切換”。
每次進行環境切換時都需要儲存當前線程的執行狀態,並載入新線程先前的狀態。 如果環境切換頻繁,CPU花在環境切換上的時間佔比就會上升,而真正處理任務的時間佔比就會下降。
如何減少環境切換。
減少線程的數量 。然而如果線程數量已經少於CPU核心數,每個CPU執行一條線程,照理來說CPU不需要進行環境切換了,但事實並非如此。
控制同一把鎖上的線程數量。如果多條線程共用同一把鎖,那麼當一條線程獲得鎖後,其他線程就會被阻塞;當該線程釋放鎖後,作業系統會從被阻塞的線程中選一條執行,從而又會出現環境切換。
因此,減少同一把鎖上的線程數量也能減少環境切換的次數。
採用無鎖並發編程。 如果減少同一把鎖上線程的數量就能減少環境切換的次數,那麼如果不用鎖,是否就能避免因競爭鎖而產生的環境切換呢。 需要根據以下兩種情況挑選不同的策略:
需要並發執行的任務是無狀態的:HASH分段 需要並發執行的任務是有狀態的:CAS演算法
死結問題
當多個線程相互等待已經被對方佔用的資源時,就會產生死結。
如何避免死結。
不要在一條線程中嵌套使用多個鎖;不要在一條線程中嵌套佔用多個電腦資源;給鎖和資源加逾時時間 如果你非要在一條線程中嵌套使用多個鎖或佔用多個資源,那你需要給鎖、資源加逾時時間,從而避免無限期的等待。
通訊機制
線程之間的通訊一共有兩種方式:共用記憶體 和 訊息傳遞。
共用記憶體:這種方式有個弊端,即需要程式員來控制線程的同步,即線程的執行次序。
訊息傳遞 :由於執行次序由並發機制完成,因此不需要程式員添加額外的同步機制,但需要聲明訊息發送和接收的代碼。
綜上所述:對於共用記憶體的通訊方式,需要進行顯示的同步,隱式的通訊; 而對於訊息傳遞的通訊方式,需要隱式的同步,顯示的通訊。
Java使用共用記憶體的方式實現多線程之間的訊息傳遞。因此,程式員需要寫額外的代碼用於線程之間的同步。
Java採用共用記憶體的方式實現訊息傳遞,而共用記憶體需要依託於同步。Java提供了synchronized、volatile關鍵字實現同步。此外volatile關鍵字還擁有一些額外的功能。