能夠將Java併發編程抽象爲三個核心問題:分工、同步和互斥。
這三個問題的產生源自對性能的需求。最初時,爲提升計算機的效率,當IO在等待時不讓CPU空閒,因而就出現了分時操做系統也就出現了併發。後來,多核CPU出現,不一樣的任務能夠同時獨立運行,因而就出現了並行【分工】。有了分工後,效率獲得了很大的提高,可是爲了更合理的安排以及控制任務的進行,就須要讓進程之間能夠通訊【同步】,讓彼此知道進度的執行。分工進行提升了效率,可是卻帶來了多線程訪問共享資源會衝突的問題。因而對共享資源的訪問又須要串行化。因此,依據現實世界的作法設計了鎖等機制來使得多線程【互斥】訪問共享資源。算法
分工的主要工做是:如何高效拆解任務並分配給線程。 編程
Java SDK併發包中的Executor
、Fork/Join
、Future
本質上都是分工方法。
併發編程中的一些設計模型也是指導如何分工:生產者——消費者
、Thread-Per-Message
、Work Thread
等。緩存
在併發編程的同步,主要指的就是線程間的協做。即當一個線程執行完了,該如何通知後續任務的線程展開工做。安全
協做通常和分工相關。Java SDK中Executor
、Fork/Join
、Future
本質上是分工方法可是也解決線程之間的協做問題(如Future異步調用,get())。Java SDK裏提供的CountDownLatch
、CyclicBarrier
、Phaser
、Exchanger
也是用於解決線程之間的協做問題。多線程
線程協做問題均可以被描述爲:當某個條件不知足時,線程須要等待,當某個條件知足使,線程須要被喚醒執行。併發
互斥指的是:在同一時刻,只容許一個線程訪問共享變量。異步
由於 可見性、有序性和原子性(後面會有文章介紹)問題,多個線程訪問同一個共享變量會致使結果的不肯定 。
爲了解決這三個問題,Java語言引入了內存模型,內存模型提供了一系列的規則,利用這些規則咱們能夠避免可見性問題、有序性問題,可是還不能徹底解決線程安全問題。性能
解決線程安全問題的核心方案仍是互斥。學習
實現互斥的核心技術就是鎖。 Java語言中synchronized
、SDK中的各類Lock均可以解決互斥問題,可是鎖卻會帶來性能問題,因而咱們就須要平衡。優化
主要方案有:分場景優化,優化讀多寫少場景:ReadWriteLock
、StampledLock
以及無鎖結構Java SDK中的原子類;其餘方案,原理爲不共享變量或者變量只容許讀,Java中提供了Thread Local
和Final
關鍵字和Copy-on-write
模式。
在看極客時間專欄《Java併發編程實戰》學習攻略時,感觸仍是比較深。平時學習知識都是「獨立」的,沒有一種「全局」觀念,也不多聯繫其餘一些理論來側面驗證學習的知識,致使學事後就很容易忘記。看了這篇專欄前言後,總結出:學習知識時,要跳出來看全景,鑽進去看本質。要知道每一種技術背後都應該有理論支持,而且這個理論多是跨領域的,因此,掌握技術背後的理論十分很重要!
針對Java併發編程應該要結合操做系統一塊兒來學習,如後面將要介紹的可見性、有序性和原子性。理解可見性就須要瞭解CPU和緩存的知識;理解原子性就須要理解操做系統的知識;不少無鎖算法也是和CPU緩存有關。要聯繫起CPU、內存、I/O之間的關係。
參考: [1]極客時間專欄王寶令《Java併發編程實戰》