從零單排Java多線程(1)

文章主要參考Java多線程編程指南(核心篇)

線程的基礎知識

我們想要創建一個線程,要不就是實現Runable接口,實現run方法,也可以繼承Thread類,覆蓋run方法,Thread實例是特殊的Runable實現類,所以在創建它的時候Java虛擬機會為其分配調用棧空間,內核線程等資源,成本要相對昂貴一點,我們在使用的時候,如果是要傳遞給其他API使用,直接使用Runable接口實現就行。

需要注意的是:啟動線程的時候,調用Runable實現類的start方法,啟動線程的本質是請求Java虛擬機運行相應的線程,這個線程具體何時能夠運行時由線程調度器(操作系統的一部分)決定

/**
*Thread類:是Runable接口的實現類,有一個含參
*的構造器Thread(Runable target);其對Runable的run方法的實現如下
**/
@Override
public void run(){
    if(target !=null){
        target.run();
    }
}

Thread類的常用方法

static Thread currentThread() :返回當前線程,即當前代碼的執行線程實例
void join() 等待相應線程運行結束,線程A調用線程B的join方法,A線程的運行會暫停,直到線程B運行結束
static void yield:使當前線程主動放棄對處理器的占用,方法不可靠,被調用時當前線程可能仍然能繼續運行
static void sleep(long millis);使當前線程休眠指定的時間

線程的生命周期狀態

New,Runable(Ready(被線程調度器選中)-->Running),Blocked(發起阻塞式IO,申請由其他線程持有的獨占資源),Waiting,Timed_waiting,Terminated;具體的在后面在說

競態

計算結果的正確性與時間有關的現象稱為競態(Race Condition)

競態的兩種模式:read-modify-write:最常見的例子就是count++操作,

load(count,r1);//將變量讀取到r1寄存器
increment(r1);//修改寄存器的值
store(count,r1);//將寄存器的值寫到count對應的內存空間里

check-then-act:讀取某個共享變量的值,根據該變量的值決定下一步的動作是什么,最常見的例子就是if判斷共享變量后進行操作

線程安全

原子性

原子操作:原子操作是針對 共享變量的操作而言的,原子操作是從改 操作的執行以外的線程來描述的。

“不可分割”含義:

  1. 訪問某個共享變量的操作從其執行線程以外的任何線程來看,該操作要么已經執行結束要么尚未發生。
  2. 訪問同一組共享變量的原子操作是不能夠被交錯的

實現原子性的方式:CAS(compare-and-swap),鎖

java對long和double型以外的任何類型的變量的寫操作都是原子操作,對任何變量的讀操作都是原子操作。

可見性

  1. JIT編譯器優化,導致共享變量更新不可見;

  2. 與計算機的存儲系統有關。程序中變量可能會分配到寄存器(Register)而不是主內存中進行存儲。每個處理器都有其存儲器,一個處理器無法讀取另外一個處理器上的寄存器的內容。但是一個處理器可以通過緩存一致性協議(Cache Coherence Protocol),讀取其他處理器的高速緩存中的數據,更新到自己的高速緩存中。稱為緩存同步(高速緩存,主內存)。為了保證共享變量更新寫入該處理器的高速緩存或者內存中(而不是在寫緩沖器中),這個過程稱為沖刷處理器。同時,如果其他處理器在此之前更新了共享變量,那么該處理器必須從其他處理器的高速緩存或者主內存中對相應的變量進行緩存同步。這個過程稱為刷新處理器緩存

    可見性保證是通過更新共享變量的處理器沖刷處理器緩存,并使讀取共享變量的處理器執行刷新處理器緩存的動作來實現
    

    java平臺中只需要使用volatile關鍵字聲明就可以保障可見性。

    JLS保證:父線程在啟動子線程之前對共享變量的更新對子線程可見;
    線程終止后該線程對共享變量的更新對于調用該線程的join方法的線程而言是可見的
    

有序性

重排序

重排序類型 重排序表現 重排序來源
指令重排序 程序順序與源代碼順序不一致 編譯器
指令重排序 執行順序與程序順序不一致 JIT編譯器、處理器
存儲子系統重排序 源代碼順序、程序順序和執行順序這三者保持一致,但是感知順序與執行順序不一致 高速緩存、寫緩沖器
指令重排序

JIT編譯器(字節碼動態生成機器碼)可能會執行指令重排序

處理器也可能會執行指令重排序,使得執行順序與程序順序不一致。處理器的亂序(Out-of-order Execution)。哪條指令就緒就執行哪條指令。指令結果被寫入重排緩沖器(ROB),ROB會進行順序提交,所以不會對單線程程序正確性產生影響。

處理器的亂序執行還采用了猜測執行(Speculation)技術。猜測執行可以導致先執行if語句的語句體。將結果臨時存放到ROB中,再來判斷if的值,如果是true就提交到高速緩存,主內存中,否則就在ROB中丟棄。

存儲子系統重排序

從處理器的角度來說,就只有讀內存操作(LOAD)(從RAM地址加載數據)和寫內存操作(STORE)

所以重排序只有四種(LoadLoad,StoreStore,LoadStore,StoreLoad),這些重排序是指在一個處理器上先后執行操作,而其他處理器對這兩個內存操作的感知順序不同。

貌似串行語義

存在數據依賴關系(兩個操作訪問同一個變量,且其中一個操作為寫操作,包括讀后寫,寫后讀,寫后寫)的語句不會被重排序,而存在控制依賴關系的語句允許被重排序(典型例子:if)

保證內存訪問的順序性

從邏輯上部分禁止重排序,從底層角度來說,禁止重排序是通過調用處理器提供相關指令(內存屏障)來實現的。

volatile,synchronized可以保證有序性。

可見性和有序性的聯系

可見性是有序性的基礎,有序性影響可見性

上下文切換

進程中的一個線程由于時間片用完或者自身原因被迫或者主動暫停其運行時,另外一個線程可以被操作系統選中占用處理器開始或者繼續其運行,這個過程稱為線程切入與切出。在切入切出時操作系統需要保存和恢復相應線程的進度信息。這個進度信息稱為上下文。一般包括通用寄存器的內容和程序計數器的內容

Thread.sleep(long millis)
Object.wait(long timeout)
Thread.yield();(不穩定)
Thread.join()
LockSupport.park()
I/O操作(讀取文件)
等待其他線程持有的鎖

一次上下文切換的時間消耗是微妙級別的

資源調度

資源調度的一個常見特性就是它能否保證公平性:如果資源的任何一個先申請者總是能夠比任何一個后申請者先獲得該資源的獨占權,那么相應的資源調度策略就稱為是公平的,否則稱為不公平。常見策略是維護一個等待隊列。

比較:

非公平調度吞吐量大:資源的持有線程釋放資源的時候,會有等待隊列中的一個線程被喚醒,而該線程從被喚醒到繼續運行需要一定時間,在這段時間內,新來的線程可以先被授予該資源的獨占權。如果新來的線程占用時間不長,它有可能在被喚醒的線程繼續運行之前釋放資源,不影響被喚醒的線程申請資源。這樣就可以減少上下文切換次數。但是如果多數線程占用資源時間相當長,那么就會使剛喚醒的線程由于被搶占又進入暫停。耗費資源。

所以,在線程占有時間較長或者申請資源頻率不高的情況下,可以使用公平調度,可以避免饑餓

但是默認一般采用非公平,提高吞吐率

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373