線程

線程和進程

進程是操作系統(tǒng)資源分配的基本單位,而線程是任務調度和執(zhí)行的基本單位,每個進程都有獨立的代碼和數(shù)據(jù)空間(進程上下文),進程切換的開銷大知牌。

線程:輕量的進程,同一類線程共享代碼和數(shù)據(jù)空間,每個線程有獨立的運行棧和程序計數(shù)器(PC),線程切換的開銷小丹拯。一個線程是一個程序內(nèi)部的順序控制流站超。

多進程:同時運行多個任務(程序)。
多線程:在同一應用程序中有多個順序流同時執(zhí)行乖酬。

線程的概念模型

●虛擬的CPU,封裝在 java. lang. Thread類中死相。

●CPU所執(zhí)行的代碼,傳遞給 Thread類。

●CPU所處理的數(shù)據(jù),傳遞給 Thread類咬像。

●Java的線程是通過 java. lang. Thread類來實現(xiàn)的算撮。、

●每個線程都是通過某個特定 Thread對象的方法run()來完成其操作的方法run()稱為線程體县昂。

構造線程的三種方法

定義一個線程類,它繼承類 Thread并重寫其中的方法run()肮柜;
提供一個實現(xiàn)接口 Runnable的類作為線程的目標對象,在初始化;
通過Callable和Future創(chuàng)建線程七芭。

一個 Thread類或者 Thread子類的線程對象時,把目標對象傳遞給這個線程實例,由該目標對象提供線程體run()素挽。

main線程已經(jīng)執(zhí)行完后,新線程才執(zhí)行完,main方法調用 thread. start()方法啟動新線程后并不等待其run方法返回就繼續(xù)運行,線程的run方法在一邊獨自運行,不影響原來的main方法的運行。

Runnable接口

只有一個run()方法,Thread類實現(xiàn)了 Runnable接囗,便于多個線程共享資源.

□Java不支持多繼承,如果已經(jīng)繼承了某個基類,便需要

現(xiàn) Runnable接口來生成多線程

口以實現(xiàn) Runnable的對象為參數(shù)建立新的線程

口sta方法啟動線程就會運行run(方法

多線程的同步控制

●有時線程之間彼此不獨立狸驳、需要同步

口線程間的互斥

同時運行的幾個線程需要共享一個(些)數(shù)據(jù)

共享的數(shù)據(jù),在某一時刻只允許一個線程對其進行操作

“生產(chǎn)者/消費者”問題

假設有一個線程負責往數(shù)據(jù)區(qū)寫數(shù)據(jù),另一個線程從同一數(shù)據(jù)

區(qū)中讀數(shù)據(jù),兩個線程可以并行執(zhí)行

如果數(shù)據(jù)區(qū)已滿,生產(chǎn)者要等消費者取走一些數(shù)據(jù)后才能再寫

當數(shù)據(jù)區(qū)空時,消費者要等生產(chǎn)者寫入一些數(shù)據(jù)后再取

●線程同步

口互斥:許多線程在同一個共享數(shù)據(jù)上操作而互不干擾,同一時刻

只能有一個線程訪問該共享數(shù)據(jù)预明。因此有些方法或程序段在同

時刻只能被一個線程執(zhí)行,稱之為監(jiān)視區(qū)

口協(xié)作:多個線程可以有條件地同時操作共享數(shù)據(jù)缩赛。執(zhí)行監(jiān)視區(qū)代

碼的線程在條件滿足的情況下可以允許其它線程進入監(jiān)視區(qū)

synchronized-一線程同步關鍵字,實現(xiàn)互斥

口用于指定需要同步的代碼段或方法,也就是監(jiān)視區(qū)

口可實現(xiàn)與一個鎖的交互。例如

synchronized(對象)(代碼段

口 synchronized的功能是:首先判斷對象的鎖是否在,如果在就獲得鎖

然后就可以執(zhí)行緊隨其后的代碼段;如果對象的鎖不在(已被其他

線程拿走),就進入等待狀態(tài),直到獲得鎖

口當被 synchronized限定的代碼段執(zhí)行完,就釋放鎖

●后臺線程

口也叫守護線程,通常是為了輔助其它線程而運行的線程

口它不妨礙程序終止

口一個進程中只要還有一個前臺線程在運行,這個進程就不會結束;如

果一個進程中的所有前臺線程都已經(jīng)結束,那么無論是否還有未結束

的后臺線程,這個進程都會結束

口“垃圾回收”便是一個后臺線程

口如果對某個線程對象在啟動(調用stat方法)之前調用了

setDaemon(true方法,這個線程就變成了后臺線程

sleep是線程類(Thread)的方法撰糠,導致此線程暫停執(zhí)行指定時間酥馍,給執(zhí)行機會給其他線程,但是監(jiān)控狀態(tài)依然保持阅酪,到時后會自動恢復旨袒。調用sleep不會釋放對象鎖。 wait是Object類的方法术辐,對此對象調用wait方法導致本線程放棄對象鎖砚尽,進入等待此對象的等待鎖定池,只有針對此對象發(fā)出notify方法(或notifyAll)后本線程才進入對象鎖定池準備獲得對象鎖進入運行狀態(tài)辉词。

誕生狀態(tài)

口線程剛剛被創(chuàng)建

就緒狀態(tài)

口線程的 start方法已被執(zhí)行

口線程已準備好運行

運行狀態(tài)

口處理機分配給了線程,線程正在運行

阻塞狀態(tài)( Blocked)

口在線程發(fā)出輸入/輸出請求且必須等待其返回

口遇到用 synchronized標記的方法而未獲得鎖

口為等候一個條件變量,線程調用wat(方法

●休眠狀態(tài)( Sleeping)

口執(zhí)行seep方法而進入休眠

死亡狀態(tài)

口線程已完成或退出

線程調度

口在單CPU的系統(tǒng)中,多個線程需要共享CPU,在任何時間點

上實際只能有一個線程在運行

口控制多個線程在同一個CPU上以某種順序運行稱為線程調度

Java虛擬機支持一種非常簡單的必孤、確定的調度算法,叫做固

定優(yōu)先級算法。這個算法基于線程的優(yōu)先級對其進行調度

考慮這些線程在運行時環(huán)境下的調度和交替執(zhí)行,也

不需要進行額外的同步,或者在調用方進行任何其他

的協(xié)調操作,調用這個對象的行為都可以獲得正確的

結果,那這個對象是線程安全的瑞躺。

Java線程安全 互斥同步敷搪、非阻塞同步、無同步方案

互斥同步

●同步的互斥實現(xiàn)方式:臨界區(qū)( Critical Section),互斥量

( Mutex),信號量( Semaphore)

● Synchronized關鍵字:經(jīng)過編譯后,會在同步塊前后形成

monitorenter和 monitorexit兩個字節(jié)碼幢哨。

口(1) synchronized同步塊對自己是可重入的,不會將自己鎖死;

口(2)同步塊在已進入的線程執(zhí)行完之前,會阻塞后面其他線程的進入

采用 synchronized,重入鎖可實現(xiàn):等待可中斷赡勘、公平鎖、鎖

可以綁定多個條件

Synchronized表現(xiàn)為原生語法層面的互斥鎖,而 RenentrantLock表

現(xiàn)為API層面的互斥鎖

●阻塞同步:互斥同步存在的問題是進行線程阻塞和喚醒所帶來的性

能問題,這種同步稱為阻塞同步( Blocking Synchronization)捞镰。這是

種悲觀并發(fā)策略

●非阻塞同步:不同于悲觀并發(fā)策略,而是使用基于沖突檢測的樂觀

并發(fā)策略,就是先進行操作,如果沒有其他線程征用共享數(shù)據(jù),則

操作成功;否則就是產(chǎn)生了沖突,采取不斷重試直到成功為止的策

種策略不需要把線程掛起,稱為非阻塞同步

●使用硬件處理器指令進行不斷重試策略(DK15以后

口測試并設置( Test-and-set)

口獲取并增加( Fetch- and-Increment)

口交換(Swap)

口比較并交換( Compare-and-Swap,簡稱CAS)

口加載鏈接,條件存儲( Load-Linked, Store-conditional簡稱LLSC)

例:java實現(xiàn)類 AtomicInteger, AtomicDouble等等闸与。

●可重入代碼:也叫純代碼。相對線程安全來說,可以保證線程安全曼振。

可以在代碼執(zhí)行過程中斷它,轉而去執(zhí)行另一段代碼,而在控制權

返回后,原來的程序不會出現(xiàn)任何錯誤几迄。

●線程本地存儲:如果一段代碼中所需要的數(shù)據(jù)必須與其他代碼共享,

那就看看這些共享數(shù)據(jù)的代碼是否能保證在同一個線程中執(zhí)行,如

果能保證,就可以把共享數(shù)據(jù)的可見范圍限定在同一個線程之內(nèi),

這樣無需同步也能保證線程之間不出現(xiàn)數(shù)據(jù)爭用問題。

鎖優(yōu)化(源自」DK6)

●自旋鎖

●自適應鎖

●鎖消除

●鎖粗化

偏向鎖

●互斥同步存在的問題:掛起線程和恢復線程都需要轉入內(nèi)核態(tài)中完

成,這些操作給系統(tǒng)的并發(fā)性能帶來很大的壓力

●自旋鎖:如果物理機器有一個以上的處理器能讓兩個或以上的線程

同時并行執(zhí)行,那就可以讓后面請求鎖的那個線程“稍等一會”,

但不放棄處理器的執(zhí)行時間,看看持有鎖的線程是否很快就會釋放

鎖冰评。為了讓線程等待,我們只需要讓線程執(zhí)行一個忙循環(huán)(自旋)

這項技術就是自旋鎖映胁。Java中自旋次數(shù)默認10次

自適應自旋

●自適應意味著鎖自旋的時間不再固定,而是由前一次在同一個鎖

上的自旋時間及鎖擁有者的狀態(tài)來決定。如果在同一個鎖對象上,

自旋等待剛剛成功獲得鎖,并且持有鎖的線程正在運行中,那么

虛擬機就會認為這次自旋也很有可能再次成功,進而它允許自旋

等待相對更長的一段時間甲雅。

鎖消除

●定義:JVM即時編譯器在運行時,對一些代碼上要求同步,但是

被檢測到不可能存在共享數(shù)據(jù)競爭的鎖進行消除

●判定依據(jù):如果判斷在一段代碼中,堆上的所有數(shù)據(jù)都不會逃逸

出去從而被其他線程訪問到,那就可以把它們當作棧上數(shù)據(jù)對待,

認為他們是線程私有的,同步加鎖自然無需進行解孙。

鎖粗化

通常我們的代碼總是將同步塊的作用范圍限制得盡量小,只在共享數(shù)

據(jù)的實際作用域中才進行同步,這樣是為了使得同步操作的數(shù)量盡可

能變小

●另一種情況是,如果一系列的連續(xù)操作都對同一個對象反復加鎖,甚至加

鎖操作是出現(xiàn)在循環(huán)體中,那即使沒有線程爭用,頻繁的進行互斥同步也

會導致不必要的性能損耗,此時只需要將同步塊范圍擴大即可。即:鎖粗

偏向鎖

●目的:消除數(shù)據(jù)無竟爭情況下的同步原語,進一步提高程序運行的性

能抛人。偏向鎖就是在無竟爭的情況下把整個同步都消除掉,連CAS操作

都不做

●偏向:意思是這個鎖會偏向于第一個獲得它的線程,如果在接下來的

執(zhí)行中,該鎖沒有被其他線程獲取,則持有偏向所得線程永遠不需要

再進行同步

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末弛姜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子妖枚,更是在濱河造成了極大的恐慌廷臼,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異荠商,居然都是意外死亡寂恬,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門莱没,熙熙樓的掌柜王于貴愁眉苦臉地迎上來初肉,“玉大人,你說我怎么就攤上這事饰躲⊙烙剑” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵嘹裂,是天一觀的道長妄壶。 經(jīng)常有香客問我,道長寄狼,這世上最難降的妖魔是什么盯拱? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮例嘱,結果婚禮上,老公的妹妹穿的比我還像新娘宁舰。我一直安慰自己拼卵,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布蛮艰。 她就那樣靜靜地躺著腋腮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪壤蚜。 梳的紋絲不亂的頭發(fā)上即寡,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機與錄音袜刷,去河邊找鬼聪富。 笑死,一個胖子當著我的面吹牛著蟹,可吹牛的內(nèi)容都是我干的墩蔓。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼萧豆,長吁一口氣:“原來是場噩夢啊……” “哼奸披!你這毒婦竟也來了?” 一聲冷哼從身側響起涮雷,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤阵面,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體样刷,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡仑扑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了颂斜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夫壁。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沃疮,靈堂內(nèi)的尸體忽然破棺而出盒让,到底是詐尸還是另有隱情,我是刑警寧澤司蔬,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布邑茄,位于F島的核電站,受9級特大地震影響俊啼,放射性物質發(fā)生泄漏肺缕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一授帕、第九天 我趴在偏房一處隱蔽的房頂上張望同木。 院中可真熱鬧,春花似錦跛十、人聲如沸彤路。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洲尊。三九已至,卻和暖如春奈偏,著一層夾襖步出監(jiān)牢的瞬間坞嘀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工惊来, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留丽涩,地道東北人。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓裁蚁,卻偏偏與公主長得像内狸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子厘擂,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,952評論 1 18
  • 本文主要講了java中多線程的使用方法昆淡、線程同步、線程數(shù)據(jù)傳遞刽严、線程狀態(tài)及相應的一些線程函數(shù)用法昂灵、概述等避凝。 首先講...
    李欣陽閱讀 2,444評論 1 15
  • 線程池ThreadPoolExecutor corepoolsize:核心池的大小,默認情況下眨补,在創(chuàng)建了線程池之后...
    irckwk1閱讀 715評論 0 0
  • 引用自多線程編程指南應用程序里面多個線程的存在引發(fā)了多個執(zhí)行線程安全訪問資源的潛在問題管削。兩個線程同時修改同一資源有...
    Mitchell閱讀 1,984評論 1 7
  • 在之前的課程中,我們已經(jīng)學習了進程相關的知識撑螺。進程是計算機程序被執(zhí)行的一個實例(instance)含思,一個進程可能由...
    夏威夷的芒果閱讀 905評論 0 2