From:Java并發編程的藝術
- 目錄
BiBi - 并發編程 -0- 開篇
BiBi - 并發編程 -1- 挑戰
BiBi - 并發編程 -2- volatile
BiBi - 并發編程 -3- 鎖
BiBi - 并發編程 -4- 原子操作
BiBi - 并發編程 -5- Java內存模型
BiBi - 并發編程 -6- final關鍵字
BiBi - 并發編程 -7- DCL
BiBi - 并發編程 -8- 線程
BiBi - 并發編程 -9- ReentrantLock
BiBi - 并發編程 -10- 隊列同步器
BiBi - 并發編程 -11- 并發容器
BiBi - 并發編程 -12- Fork/Join框架
BiBi - 并發編程 -13- 并發工具類
BiBi - 并發編程 -14- 線程池
BiBi - 并發編程 -15- Executor框架
1. 線程切換問題
單核處理器通過時間切片可以支持多線程執行。線程在切換之前會保存該任務狀態,用于下次切換回來再加載該線程的狀態。線程從保存到再次加載的過程稱為一次【上下文切換Content Switch】
下面例子中,什么時候考慮將A、B事件放在不同線程中去處理呢?
當N < 1萬時,開線程耗時多。
當N > 1千萬時,開線程耗時少。【性能提升約1倍】
// A、B事件處理獨立
private void test() {
for (int i = 0; i < N; ++i) {
// 處理事件A
}
for (int i = 0; i < N; ++i) {
// 處理事件B
}
}
下載20部電影,是一個一個下載快,還是同時下載20部快呢?
這就要考慮資源的限制,如:
硬件資源限制:服務器帶寬(2Mb/s)、硬盤讀寫速度和CPU的處理速度;
軟件資源限制:數據庫的連接數、socket連接數。
如果由于資源限制,并行的程序變為串行執行,那么就會增加上下文切換和資源調用的時間,從而導致程序執行更慢.
2. 如何減少上下文切換
1)無鎖并發。如ConcurrentHashMap將數據的ID按照Hash算法取模分段,不同的線程處理不同的數據段。
2)CAS【比較并替換 - Compare And Swap】算法。如Java的Atomic包中的AtomicInteger、AtomicBoolean等,不需要加鎖。
3)減少線程數量。主要針對線程池的使用,當任務較少而線程較多時,會導致大量線程處于等待狀態,從而使性能下降。減少等待狀態的線程,能夠減少上下文切換次數。【所以,線程池的大小要因需而異】
3. 如何避免死鎖
1)避免一個線程同時使用多個鎖。
2)避免一個鎖同時占用多個資源,盡量保證一個鎖只占用一個資源。
3)使用定時鎖。
4)數據庫鎖,加鎖和解鎖必須在一個數據庫連接里。
因為異常導致沒有釋放鎖也會引起死鎖現象。