1. 併發編程面臨的問題
併發編程是爲了讓程序運行得更快,但是並不是啓動更多的線程就能讓程序最大限度的併發執行,通常在併發編程中會遇到下面的問題.
1.1 上下文切換
CPU通過時間片非配算法來循環執行任務,當前任務執行一個時間片後會切換到下一個任務.在切換時會保存上一個任務的狀態,以便這個任務再次執行時,可以在加載這個任務的狀態.所以任務從保存到再加載的過程就是一次上下文切換.
1.1.1 多線程不一定比單線程快
測試多線程是否一定比單線程快 執行鏈接中的代碼發現,當併發操作較少時,併發執行的速度比串行慢,因爲併發執行時,線程有創建和上下文切換的開銷.
1.1.2 如何減少上下文切換
- 無鎖併發編程.多線程競爭鎖時會引起上下文切換,所以多線程處理數據時可以避免使用鎖(如將數據的ID按照Hash算法取模分段,不同的線程處理不同段的數據).
- CAS算法.Java的Atomic包便是使用CAS算法來更新數據,而不加鎖.
- 使用最少線程. 避免創建不需要的線程.
- 協程:在單線程裏實現多任務的調度,並在單線程裏維持多個任務間的切換.
1.2 死鎖
造成死鎖的代碼 鏈接中的代碼會造成死鎖,代碼中thread1和thread2互相等待對方釋放鎖.避免死鎖的方法如下:
- 避免一個線程同時獲取多個鎖
- 避免一個線程在鎖內同時佔用多個資源,儘量保證每個鎖只佔用一個資源
- 嘗試使用定時鎖
- 對於數據庫鎖,加鎖和解鎖必須在一個連接裏,否則可能解鎖失敗.
1.3 資源限制
程序的運行速度受限於計算機的硬件或軟件資源.硬件限制有帶寬的上傳/下載速度,硬盤讀寫和CPU的處理速度;軟件限制有數據庫的連接數和socket的連接數等.
爲了解決資源限制,硬件可以換設備,採用集羣併發執行程序;
軟件限制可以使用連接池將數據庫和socket連接複用.