【Java併發基礎】併發編程領域的三個問題:分工、同步和互斥

前言

能夠將Java併發編程抽象爲三個核心問題:分工、同步和互斥。
這三個問題的產生源自對性能的需求。最初時,爲提升計算機的效率,當IO在等待時不讓CPU空閒,因而就出現了分時操做系統也就出現了併發。後來,多核CPU出現,不一樣的任務能夠同時獨立運行,因而就出現了並行【分工】。有了分工後,效率獲得了很大的提高,可是爲了更合理的安排以及控制任務的進行,就須要讓進程之間能夠通訊【同步】,讓彼此知道進度的執行。分工進行提升了效率,可是卻帶來了多線程訪問共享資源會衝突的問題。因而對共享資源的訪問又須要串行化。因此,依據現實世界的作法設計了鎖等機制來使得多線程【互斥】訪問共享資源。算法

分工(性能)

分工的主要工做是:如何高效拆解任務並分配給線程。   編程

Java SDK併發包中的ExecutorFork/JoinFuture本質上都是分工方法。
併發編程中的一些設計模型也是指導如何分工:生產者——消費者Thread-Per-MessageWork Thread等。緩存

 同步(性能)

在併發編程的同步,主要指的就是線程間的協做。即當一個線程執行完了,該如何通知後續任務的線程展開工做。安全

協做通常和分工相關。Java SDK中ExecutorFork/JoinFuture本質上是分工方法可是也解決線程之間的協做問題(如Future異步調用,get())。Java SDK裏提供的CountDownLatchCyclicBarrierPhaserExchanger也是用於解決線程之間的協做問題。多線程

線程協做問題均可以被描述爲:當某個條件不知足時,線程須要等待,當某個條件知足使,線程須要被喚醒執行併發

互斥(正確性/線程安全)

互斥指的是:在同一時刻,只容許一個線程訪問共享變量。異步

由於 可見性有序性原子性(後面會有文章介紹)問題,多個線程訪問同一個共享變量會致使結果的不肯定 。
爲了解決這三個問題,Java語言引入了內存模型,內存模型提供了一系列的規則,利用這些規則咱們能夠避免可見性問題、有序性問題,可是還不能徹底解決線程安全問題。性能

解決線程安全問題的核心方案仍是互斥學習

實現互斥的核心技術就是鎖。 Java語言中synchronized、SDK中的各類Lock均可以解決互斥問題,可是鎖卻會帶來性能問題,因而咱們就須要平衡。優化

主要方案有:分場景優化,優化讀多寫少場景:ReadWriteLockStampledLock以及無鎖結構Java SDK中的原子類;其餘方案,原理爲不共享變量或者變量只容許讀,Java中提供了Thread LocalFinal關鍵字和Copy-on-write 模式。

小結

在看極客時間專欄《Java併發編程實戰》學習攻略時,感觸仍是比較深。平時學習知識都是「獨立」的,沒有一種「全局」觀念,也不多聯繫其餘一些理論來側面驗證學習的知識,致使學事後就很容易忘記。看了這篇專欄前言後,總結出:學習知識時,要跳出來看全景,鑽進去看本質。要知道每一種技術背後都應該有理論支持,而且這個理論多是跨領域的,因此,掌握技術背後的理論十分很重要!
針對Java併發編程應該要結合操做系統一塊兒來學習,如後面將要介紹的可見性、有序性和原子性。理解可見性就須要瞭解CPU和緩存的知識;理解原子性就須要理解操做系統的知識;不少無鎖算法也是和CPU緩存有關。要聯繫起CPU、內存、I/O之間的關係。

參考: [1]極客時間專欄王寶令《Java併發編程實戰》

相關文章
相關標籤/搜索