Java多線程
一 . happens-before 模型
1.1 ?happens-before 定義
happens-before 規(guī)則可以幫助我們有效的判斷操作的順序 , 幫助我們理解多線程的數(shù)據(jù)流動
如果一個操作 happens-before 另一個操作,那么第一個操作的執(zhí)行結(jié)果,將對第二個操作可見,而且第一個操作的執(zhí)行順序,排在第二個操作之前。
兩個操作之間存在 happens-before 關(guān)系,并不意味著一定要按照 happens-before 原則制定的順序來執(zhí)行。如果重排序之后的執(zhí)行結(jié)果與按照 happens-before 關(guān)系來執(zhí)行的結(jié)果一致,那么這種重排序并不非法。
學(xué)習(xí)更多知識,請點擊:https://www.bilibili.com/video/BV1Li4y1P764/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1yy4y147TY/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1gA411T7cc/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV19V411v7PH/
1.2??happens-before 規(guī)則
程序次序規(guī)則:一個線程內(nèi),按照代碼順序,書寫在前面的操作,happens-before 于書寫在后面的操作。
鎖定規(guī)則:一個 unLock 操作,happens-before 于后面對同一個鎖的 lock 操作。
volatile 變量規(guī)則:對一個變量的寫操作,happens-before 于后面對這個變量的讀操作。
傳遞規(guī)則:如果操作 A happens-before 操作 B,而操作 B happens-before 操作C,則可以得出,操作 A happens-before 操作C
線程啟動規(guī)則:Thread 對象的 start 方法,happens-before 此線程的每個一個動作。
線程中斷規(guī)則:對線程 interrupt 方法的調(diào)用,happens-before 被中斷線程的代碼檢測到中斷事件的發(fā)生。
線程終結(jié)規(guī)則:線程中所有的操作,都 happens-before 線程的終止檢測,我們可以通過Thread.join() 方法結(jié)束、Thread.isAlive() 的返回值手段,檢測到線程已經(jīng)終止執(zhí)行。
對象終結(jié)規(guī)則:一個對象的初始化完成,happens-before 它的 finalize() 方法的開始
學(xué)習(xí)更多知識,請點擊:https://www.bilibili.com/video/BV1Li4y1P764/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1yy4y147TY/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1gA411T7cc/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV19V411v7PH/
1.3 ?其他規(guī)則
將一個元素放入一個線程安全的隊列的操作,happens-before 從隊列中取出這個元素的操作。
將一個元素放入一個線程安全容器的操作,happens-before 從容器中取出這個元素的操作。
在 CountDownLatch 上的 countDown 操作,happens-before CountDownLatch 上的 await 操作。
釋放 Semaphore 上的 release 的操作,happens-before 上的 acquire 操作。
Future 表示的任務(wù)的所有操作,happens-before Future 上的 get 操作。
向 Executor 提交一個 Runnable 或 Callable 的操作,happens-before 任務(wù)開始執(zhí)行操作。


二 . ?重排序
為了提高性能,處理器和編譯器常常會對指令進行重排序 , 其主要目的是在不改變程序執(zhí)行結(jié)果的前提下,盡可能提高程序的運行效率
在單線程環(huán)境下,不能改變程序運行的結(jié)果。
存在數(shù)據(jù)依賴關(guān)系的情況下,不允許重排序。
多線程情況下 , 當代碼中存在控制依賴性時,會影響指令序列的執(zhí)行的并行度,所以編譯器和處理器會采用猜測執(zhí)行來克服控制依賴對并行度的影響
總結(jié) : 無法通過 happens-before 原則推導(dǎo)出來的,JMM 允許任意的排序。
學(xué)習(xí)更多知識,請點擊:https://www.bilibili.com/video/BV1Li4y1P764/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1yy4y147TY/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1gA411T7cc/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV19V411v7PH/
as-if-serial 語義
所有的操作均可以為了優(yōu)化而被重排序,但是你必須要保證重排序后執(zhí)行的結(jié)果不能被改變,編譯器、runtime、處理器都必須遵守 as-if-serial 語義
as-if-serial 只保證單線程環(huán)境,多線程環(huán)境下無效
JIT 優(yōu)化原則
盡可能地優(yōu)化程序正常運行下的邏輯,哪怕以?catch?塊邏輯變得復(fù)雜為代價。
三 . ?線程的 CPU 時間片
Java中線程會按優(yōu)先級分配CPU時間片運行
當前運行線程主動放棄CPU,JVM暫時放棄CPU操作(基于時間片輪轉(zhuǎn)調(diào)度的JVM操作系統(tǒng)不會讓線程永久放棄CPU,或者說放棄本次時間片的執(zhí)行權(quán)),例如調(diào)用yield()方法。
當前運行線程因為某些原因進入阻塞狀態(tài),例如阻塞在I/O上。
當前運行線程結(jié)束,即運行完run()方法里面的任務(wù)。
yield 放棄 CPU
yield操作并不會永遠放棄CPU,僅僅只是放棄了此次時間片,把剩下的時間讓給別的線程
學(xué)習(xí)更多知識,請點擊:https://www.bilibili.com/video/BV1Li4y1P764/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1yy4y147TY/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1gA411T7cc/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV19V411v7PH/
IO 柱塞
運行程序?qū)⒂袃蓷l線程工作,ioThread每次遇到I/O阻塞就放棄當前的時間片,而主線程則按JVM分配的時間片正常運行
CPU 優(yōu)先級
Java把線程優(yōu)先級分成10個級別,線程被創(chuàng)建時如果沒有明確聲明則使用默認優(yōu)先級,JVM將根據(jù)每個線程的優(yōu)先級分配執(zhí)行時間的概率。有三個常量 :
Thread.MIN_PRIORITY ?: 最小優(yōu)先級值(1)
Thread.NORM_PRIORITY : 默認優(yōu)先級值(5)
Thread.MAX_PRIORITY : 最大優(yōu)先級值(10)。
線程的調(diào)度策略決定上層多線程運行機制,JVM的線程調(diào)度器實現(xiàn)了搶占式調(diào)度,每條線程執(zhí)行的時間由它分配管理,它將按照線程優(yōu)先級的建議對線程執(zhí)行的時間進行分配,優(yōu)先級越高,可能得到CPU的時間則越長。
學(xué)習(xí)更多知識,請點擊:https://www.bilibili.com/video/BV1Li4y1P764/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1yy4y147TY/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1gA411T7cc/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV19V411v7PH/
四 .內(nèi)存屏障
硬件層提供了一系列的內(nèi)存屏障 memory barrier / memory fence(Intel的提法)來提供一致性的能力
幾種主要的內(nèi)存屏障 :
lfence,是一種Load Barrier 讀屏障
sfence, 是一種Store Barrier 寫屏障
mfence, 是一種全能型的屏障,具備ifence和sfence的能力
帶Lock前綴類,Lock不是一種內(nèi)存屏障,但是它能完成類似內(nèi)存屏障的功能。
Lock會對CPU總線和高速緩存加鎖,可以理解為CPU指令級的一種鎖。
它后面可以跟ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, and XCHG等指令。
內(nèi)存屏障的能力
阻止屏障兩邊的指令重排序
強制把寫緩沖區(qū)/高速緩存中的臟數(shù)據(jù)等寫回主內(nèi)存,讓緩存中相應(yīng)的數(shù)據(jù)失效
**內(nèi)存屏障最常見的地方就是 Volatile **
五. ?CPU
CPU 高速緩存原理
Java內(nèi)存模型中每個線程的工作內(nèi)存實際上就是寄存器以及高速緩存的抽象 , ?各個核心直接通過系統(tǒng)總線連接 , 而總線是一種共享資源 , 這就意味著資源競爭.
計算機的局部性原理
局部性原理是緩存技術(shù)的底層理論基礎(chǔ)。局部性包括兩種形式:
時間局部性,一個具有良好時間局部性的程序中,被引用過一次的存儲器位置很可能在不遠的將來再被多次引用
空間局部性,一個具有良好空間局部性的程序中,如果一個存儲器位置被引用了一次,那么程序很可能在不遠的將來引用附近的一個存儲器位置
存儲器體系結(jié)構(gòu) :
存儲器呈現(xiàn)金字塔結(jié)構(gòu) , 主要包括寄存器 , 高速緩存 , 主存等幾個概念 , 存儲器有以下幾個特點 :
學(xué)習(xí)更多知識,請點擊:https://www.bilibili.com/video/BV1Li4y1P764/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1yy4y147TY/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1gA411T7cc/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV19V411v7PH/
一層存儲器只和下層存儲器打交道,不會跨級訪問
下層作為上層的一個緩存。CPU要訪問的數(shù)據(jù)的最終一般都經(jīng)過主存,主存作為下層其他設(shè)備的一個緩存,其他設(shè)備的數(shù)據(jù)最終都要進入主存才能被CPU訪問到
CPU 高速緩存核心原理
TODO @?blog.csdn.net/iter_zc/art…

六. 內(nèi)存模型之一致性
一致性的滿足 @?blog.csdn.net/iter_zc/art…
在單機器多CPU的情況下,多CPU并發(fā)執(zhí)行,共用一個內(nèi)存,一般通過共享內(nèi)存的方式來處理一致性問題,通過定義滿足不同一致性需求的內(nèi)存模型來解決內(nèi)存一致性問題(Memory Consistency)
在分布式環(huán)境中,多臺機器多CPU通過網(wǎng)絡(luò)來并發(fā)執(zhí)行,一般通過消息通信的方式來處理一致性問題 (Paxos協(xié)議 , Zab協(xié)議)
6.1 一致性分類
嚴格一致性 Strict Consistency 線性一致性 Linearizability
所有的讀寫操作都按照全局的時序來排列執(zhí)行 , 所有的CPU需要共享一個全局的時鐘順序 , 且按照該順序執(zhí)行
順序一致性 Sequential Consistency
對每個單個CPU來說,它看到自己程序的執(zhí)行順序始終是和程序定義是一致的(單個CPU角度)
每個CPU看到的其他CPU的寫操作都是按照相同的順序執(zhí)行的,大家看到的最終執(zhí)行的視圖是一致的(從全局的角度)
單個CPU對共享變量的寫操作馬上對其他CPU可見
因果一致性 Causal Consistency
因果一致性是一種弱的順序一致性,只有有因果關(guān)系的數(shù)據(jù)才需要保證順序一致性,沒有因果關(guān)系的數(shù)據(jù)不需要保證順序一致性
通俗來說就是 B 對 x 的寫操作 W(x)B 會依賴于 A 對 x 的寫操作 , 即對外展現(xiàn)為 W(x)a, W(x)b
處理器一致性/ PRAM(Piplined RAM) 管道式存儲器
只要求從一個處理器來的寫操作按照同樣的順序被其他處理器看到,不同處理器的寫操作可以按照不同的順序被看到
就是說它不保證有因果關(guān)系的寫操作按照執(zhí)行的順序執(zhí)行
弱一致性 Weak Consistency
弱一致性只對被同步操作保護的共享變量而言,規(guī)定了只有對共享變量的同步操作完成之后,共享數(shù)據(jù)才可能保持一致性.在同步操作過程中,是不保證一致性的,單個處理器對共享變量的修改對其他處理器是不可見的。相比與嚴格的順序一致性,它只保持了執(zhí)行順序上的順序一致性,至于可見性必須要等待同步操作結(jié)束
學(xué)習(xí)更多知識,請點擊:https://www.bilibili.com/video/BV1Li4y1P764/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1yy4y147TY/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1gA411T7cc/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV19V411v7PH/
對同步變量的讀寫按照順序一致性
只有所有對同步變量的寫操作完成之后才能對同步變量進行訪問
只有所有對同步變量的訪問(讀/寫)完成后才能對同步變量訪問
釋放一致性 Release Consistency
釋放一致性規(guī)定了對同步變量的釋放操作后,就對同步變量的狀態(tài)廣播到其他處理器
進入一致性 Entry Consistency
進入同步變量時,獲取同步變量的最新狀態(tài)
緩存一致性 Cache Consistency
TODO
九 . ?多線程模型
9 .1 并行模型
并行 Worker : (許多 java.util.concurrent 包下的并發(fā)工具都使用了這種模型)
并行 worker 的核心思想是,它主要有兩個進程即代理人和工人,Delegator 負責(zé)接收來自客戶端的任務(wù)并把任務(wù)下發(fā),交給具體的 Worker 進行處理,Worker 處理完成后把結(jié)果返回給 Delegator,在 Delegator 接收到 Worker 處理的結(jié)果后對其進行匯總,然后交給客戶端。
學(xué)習(xí)更多知識,請點擊:https://www.bilibili.com/video/BV1Li4y1P764/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1yy4y147TY/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1gA411T7cc/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV19V411v7PH/


9 .2 響應(yīng)式 - 事件驅(qū)動系統(tǒng) : Actor 模型
在 Actor 模型中,每一個 Actor 其實就是一個 Worker, 每一個 Actor 都能夠處理任務(wù)。
簡單來說,Actor 模型是一個并發(fā)模型,它定義了一系列系統(tǒng)組件應(yīng)該如何動作和交互的通用規(guī)則,最著名的使用這套規(guī)則的編程語言是 Erlang。一個參與者Actor對接收到的消息做出響應(yīng),然后可以創(chuàng)建出更多的 Actor 或發(fā)送更多的消息,同時準備接收下一條消息。

9 .3 ?響應(yīng)式 - 事件驅(qū)動系統(tǒng) : Channels 模型 .
在 Channel 模型中,worker 通常不會直接通信,與此相對的,他們通常將事件發(fā)送到不同的 通道(Channel)上,然后其他 worker 可以在這些通道上獲取消息,下面是 Channel 的模型圖

學(xué)習(xí)更多知識,請點擊:https://www.bilibili.com/video/BV1Li4y1P764/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1yy4y147TY/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV1gA411T7cc/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://www.bilibili.com/video/BV19V411v7PH/
作者:AntBlack
鏈接:https://juejin.cn/post/6939852157478764551
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。