Java 併發這塊,比較難,爲啥呢,因爲這一個知識點,那一個知識點的,特別碎
所以這個時候最重要的就是要對 Java 併發這塊的知識有一個全貌
我先上一張圖,下面的內容主要就是圍繞這張圖來說:
主要矛盾
凡事都有它的發展規律, Java 併發也是如此,不可能說突然這個事物就出來了
那爲什麼會有併發編程呢?這就要說一說 CPU/內存/磁盤 它們之間的速度差異了
應該都知道 CPU 的速度非常快,比內存的速度還要快,如果拿"天上一天,地上一年"來比喻 CPU 和內存之間的差異我覺得也是很合適的.內存的速度又要比磁盤的速度要快,快的量級是十倍都不止,那麼可想而知, CPU 的一天,對於磁盤來說可能就是十年了.
怎麼辦呢?既然 CPU 這麼快,那就用一用 CPU 緩存嘛,我先把一些數據放在 CPU 緩存中,這樣是不是讀取的速度就快一些;在操作系統層面,增加進程/線程,這樣如果這個線程不用 CPU 了,趕緊換另外一個線程使用;編譯程序在進行編譯的時候,可以將指令進行一下優化
這樣看起來是不錯,但是它們分別帶來了不同的問題.比如 CPU 緩存這一塊,緩存最大的問題是什麼?是數據不一致問題,源數據都已經做了更新,但是在 CPU 緩存中沒有去做這個更新,此時別的程序來讀,就很容易導致可見性問題;操作系統增加了進程/線程,那麼線程之間的切換就沒有辦法導致原子性問題,比如經典的 i++ ;編譯器不是會對指令進行優化嗎,那就沒辦法保證優化之後的結果還是原來的執行順序,這就導致了有序性問題
JMM
有問題就要有解決方案嘛, JMM 的存在就解決了可見性和有序性的問題,怎麼解決的呢?
這就要說, Happens-Before 規則, volatile , synchronized , final 這些內容了.
以前寫過一些這部分的內容,就直接放鏈接了:
[Java 併發]爲什麼會有重排序?和 happens-before 有啥關係
[Java 併發]你確定你瞭解 volatile ?
[Java 併發]深入淺出 synchronized 與鎖
核心
併發編程的核心主要有 3 點:
- 分工
因爲是多線程嘛,那就肯定要分工好咯,就像一個團隊,這個功能你來開發,那個功能他來開發,如果兩個人開發同樣一個任務,那不就有點兒浪費資源了嘛
在併發編程這塊,分工就是由 Executor/線程池/Fork/Join 來實現的 - 協作
分工好了,接下來就是怎麼互相協作一起做好,協作的核心技術是管程,其實分工裏面就有協作的解決方案,比如 Fork/Join 它就有定義分工完了怎麼再協作,所以導圖就沒有列出,主要說了 CountDownLantch/CyclicBarrier/Monitor ,因爲接下來我想針對這幾個方面去寫幾篇文章(不偷懶的話; - 互斥
分工/同步主要說的是性能,但是在併發程序裏面還要求正確,也就是"線程安全",解決這個問題的核心就是互斥.
解決互斥的方案就是鎖嘛.所以就有無鎖和互斥鎖兩種方案.具體可以見思維導圖
思維導圖裏面涉及到的內容,接下來我會慢慢都寫出來(就是不確定什麼時候寫完
有時候我覺得自己扎到細節裏面去之後,就不知道在做什麼了,需要再看看全貌,也就是這張導圖
也算是對自己接下來要寫的內容的一個總結吧
最後推薦幾篇文章,相信你看完再看這個導圖會有不小的收穫
文章推薦:
以上,非常感謝您的閱讀~