併發編程簡介
將串行執行部分編程併發執行,但要考慮上下文切換和資源調度的時間
併發編程的意義及影響多線程的因素
併發編程的目的是爲了讓程序運行得更快,可是,並非啓動更多的線程就能讓程序最 大限度地併發執行。
影響多線程運行速度的緣由有上下文切換、死鎖,以及硬件和軟件的資源限制等
資源限制:硬件資源和軟件資源
硬件資源:如寬帶 硬盤讀寫 內存 cpu處理速度
軟件資源:如數據庫鏈接數、socket鏈接數等
上下文切換
即便是單核處理器也支持多線程執行代碼,CPU經過給每一個線程分配CPU時間片來實現這個機制。時間片是CPU分配給各個線程的時間,由於時間片很是短,因此CPU經過不停地切
換線程執行,讓咱們感受多個線程是同時執行的,時間片通常是幾十毫秒(ms)。
CPU經過時間片分配算法來循環執行任務,當前任務執行一個時間片後會切換到下一個任務。可是,在切換前會保存上一個任務的狀態,以便下次切換回這個任務時,能夠再加載這個任務的狀態。因此任務從保存到再加載的過程就是一次上下文切換。
上下文切換也會影響多線程的執行速度
多線程程序的評量標準
安全性——不損壞對象
暗指對象的字段所取得的值並不是預期值
生存性——進行必要的處理
複用性——可再利用類
性能——能快速、大量進行處理java
多線程執行不必定比串行執行快
除了上面提到的影響多線程的緣由,還有線程有建立和上下文切換的開銷
但能夠經過調優減小上下文切換的方法有無鎖併發編程、CAS算法、使用最少線程和使用協程。由於多線程競爭鎖時,會引發上下文切換。算法
協程:在單線程裏實現多任務的調度,並在單線程裏維持多個任務間的切換。
併發工具分析
vmstat能夠測量上下文切換的次數
用jstack命令dump線程信息,能夠查看指定pid的進程裏的線程都在作什麼,例如:jstack pid,可使用jstack pid > dump,而後使用:
grep java.lang.Thread.State dump17|awk '{print $2$3$4$5}'|sort|uniq -c作統計,能夠查看當前運行RUNNABLE、WAITING等狀態的數量
死鎖
兩個線程分別獲取了鎖定,互相等待另外一線程解除鎖定的現象。發生死鎖時,哪一個線程都不能執行下去,因此程序就失去了生命性。
避免一個線程同時獲取多個鎖,避免一個線程在鎖內同時佔用多個資源,儘可能保證每一個鎖只佔用一個資源。嘗試使用定時鎖,使用lock.tryLock(timeout)來替代使用內部鎖機制。對於數據庫鎖,加鎖和解鎖必須在一個數據庫鏈接裏,不然會出現解鎖失敗的狀況。數據庫
引用書籍:《Java併發編程藝術》《Java多線程設計模式》編程