Java中的線程---基礎(chǔ)知識

今天剛剛參加了一次面試震放,被面試官的關(guān)于線程的提問生生碾壓了筷厘。重整旗鼓,總結(jié)一下關(guān)于線程的基礎(chǔ)知識前普,相信也可以幫到一批小伙伴的肚邢。首先分享一下基礎(chǔ)知識。南玻萬:0

線程與進程的區(qū)別

區(qū)別詳解請移步鏈接中的文章已經(jīng)把區(qū)別整理的很完善了拭卿,同學們可以自行移步查看骡湖。我在這里寫一下我自己總結(jié)的它們之間的區(qū)別:

  • 它們是不同的操作系統(tǒng)管理資源的方式。
    • 進程是系統(tǒng)進行資源分配和調(diào)度的一個獨立單位峻厚;
    • 線程是CPU進行資源分配和調(diào)度的基本單位响蕴;
  • 一個程序至少有一個進程,一個進程又至少有一個線程惠桃。
  • 進程有自己獨立的地址空間浦夷,一個進程崩潰后,一般不會對其他進程產(chǎn)生影響辜王。而線程只是一個進程的不同執(zhí)行路徑劈狐,線程有自己的堆棧和局部變量,但線程沒有單獨的地址空間呐馆。一個線程死掉就等于整個進程死掉肥缔,所以多進程的程序比多線程的程序更健壯。但進程切換時汹来,耗費資源較大续膳,效率要差一些改艇。

線程的狀態(tài)

下面這張圖片展示了線程的所有狀態(tài)和狀態(tài)之間的互相轉(zhuǎn)換:


線程狀態(tài)圖
  • 可運行(runnable):線程創(chuàng)建后調(diào)用了.start()方法。該線程位于可運行的線程池中坟岔,等待被線程調(diào)度選中谒兄,獲得CPU的資源;
  • 運行(running):可運行狀態(tài)(runnable)的線程獲得了CPU的時間片(timeslice)炮车,執(zhí)行線程內(nèi)的代碼舵变;
  • 阻塞(block):阻塞狀態(tài)是指線程暫時放棄了CPU的使用權(quán),即讓出了CPU的時間片瘦穆。阻塞狀態(tài)的線程直到轉(zhuǎn)換成可運行狀態(tài)進入到可運行線程池中纪隙,才會有機會再次獲得CPU的時間片進入到運行狀態(tài)。使線程進入阻塞狀態(tài)的情況由一下幾種:
    • 等待阻塞:線程執(zhí)行了wait()方法扛或,JVM會將線程放入到等待隊列(waitting queue)中绵咱。
    • 同步阻塞:運行的線程在獲取對象的同步鎖時,如該同步鎖被別的線程占用熙兔,則JVM會把該線程放入到鎖池(lock pool)中悲伶。
    • 其他阻塞:運行中的線程執(zhí)行了Thread.sleep()方法或b.join()方法,或者當前線程執(zhí)行到了I/O操作時住涉。JVM會把線程切換到阻塞狀態(tài)麸锉,當sleep()方法休眠結(jié)束時、b線程執(zhí)行完成后舆声,I/O操作完成后花沉,該線程又會轉(zhuǎn)換到Runnable狀態(tài)。
  • 死亡(dead):線程run()媳握、main() 方法執(zhí)行結(jié)束碱屁,或者因異常退出了run()方法,則該線程結(jié)束生命周期蛾找。死亡的線程不可再次復生娩脾。

同步鎖(synchonrize)的介紹

相信很多同學應該都和我差不多只知道這個關(guān)鍵字的簡單實用,對于很多細節(jié)其實并不是很清楚打毛,這里我同大家一起分享關(guān)于同步鎖的正確使用柿赊。
首先我們大家都應該知道每個對象都有一個鎖標志,被synchonrize關(guān)鍵字修飾的變量或方法將被上鎖幻枉,同一時刻只能被單一線程訪問碰声。當前線程訪問完數(shù)據(jù)后釋放鎖標志,其他線程才可以進行訪問展辞。這里還需要給大家補充一下線程常用方法與同步鎖之間存在的關(guān)系,以下表格可以清晰的展示這一點:

方法 是否釋放鎖 備注
wait wait和notify/notifyAll是成對出現(xiàn)的, 必須在synchronize塊中被調(diào)用
sleep 可使低優(yōu)先級的線程獲得執(zhí)行機會
yield yield方法使當前線程讓出CPU占有權(quán), 但讓出的時間是不可設(shè)定的

對以上方法的備注我還引入一些更具體的解釋(點擊給進入原作者的文章)万牺。如下:

  • sleep()
    使當前線程(即調(diào)用該方法的線程)暫停執(zhí)行一段時間罗珍,讓其他線程有機會繼續(xù)執(zhí)行洽腺,但它并不釋放對象鎖。也就是說如果有synchronized同步塊覆旱,其他線程仍然不能訪問共享數(shù)據(jù)蘸朋。注意該方法要捕捉異常。
    例如有兩個線程同時執(zhí)行(沒有synchronized)一個線程優(yōu)先級為MAX_PRIORITY扣唱,另一個為MIN_PRIORITY藕坯,如果沒有Sleep()方法,只有高優(yōu)先級的線程執(zhí)行完畢后噪沙,低優(yōu)先級的線程才能夠執(zhí)行炼彪;但是高優(yōu)先級的線程sleep(500)后,低優(yōu)先級就有機會執(zhí)行了正歼。
    總之辐马,sleep()可以使低優(yōu)先級的線程得到執(zhí)行的機會,當然也可以讓同優(yōu)先級局义、高優(yōu)先級的線程有執(zhí)行的機會喜爷。

  • yield()
    該方法與sleep()類似,只是不能由用戶指定暫停多長時間萄唇。這里還需補充一點檩帐,yield()方法對應了如下操作: 先檢測當前是否有相同優(yōu)先級的線程處于同可運行狀態(tài), 如有, 則把 CPU 的占有權(quán)交給此線程, 否則繼續(xù)運行原來的線程.。所以yield()方法稱為“退讓”, 它把運行機會讓給了同等優(yōu)先級的其他線程另萤。

  • wait()和notify()湃密、notifyAll()

這三個方法用于協(xié)調(diào)多個線程對共享數(shù)據(jù)的存取,wait()有出讓Object鎖的語義, 要想出讓鎖, 前提是要先獲得鎖, 所以要先用synchronized獲得鎖之后才能調(diào)用wait()仲墨, notify原因類似勾缭。
wait()方法使當前線程暫停執(zhí)行并釋放對象鎖標示,讓其他線程可以進入synchronized數(shù)據(jù)塊目养,當前線程被放入對象等待池中俩由。當調(diào)用notify()方法后,將從對象的等待池中移走一個任意的線程并放到鎖標志等待池中癌蚁,只有鎖標志等待池中線程能夠獲取鎖標志幻梯;如果鎖標志等待池中沒有線程,則notify()不起作用努释。
notifyAll()則從對象等待池中移走所有等待那個對象的線程并放到鎖標志等待池中碘梢。

同步鎖(synchonrize)的使用

synchronize關(guān)鍵字主要有下面5種用法

  1. 在方法上進行同步, 分為(1)instance method/(2)static method, 這兩個的區(qū)別后面說
  2. 在內(nèi)部塊上進行同步, 分為(3)synchronize(this), (4)synchonrize(XXX.class), (5)synchonrize(mutex)

代碼示例如下:

private int value = 0;
private final Object mutex = new Object();
public synchronized int incAndGet0() {
       return ++value;
 }
public static synchonrize int incAndGet1();
 public int incAndGet2() {
        synchronized(this){
            return ++value;
        }
    }
public int incAndGet3() {
       synchronized(SyncMethod.class){
            return ++value;
        }
    }
public int incAndGet4() {
       synchronized(mutex){
            return ++value;
        }
    }

  1. 作為修飾符加在方法聲明上, synchronized修飾非靜態(tài)方法時表示鎖住了調(diào)用該方法的堆對象, 修飾靜態(tài)方法時表示鎖住了這個類在方法區(qū)中的類對象。
  • 關(guān)于Java中的堆伐蒂、棧和方法區(qū)煞躬,請大家移步很詳細的介紹了以上內(nèi)容,感覺作為程序員真是學海無涯啊。
  1. synchronized(X.class) 使用類對象作為監(jiān)控恩沛。 同一時間只有一個線程可以能訪問塊中資源在扰。
  2. synchronized(this)和synchronized(mutex) 都是對象鎖, 同一時間每個實例都保證只能有一個實例能訪問塊中資源。

以上就是關(guān)于synchonrize關(guān)鍵字的基礎(chǔ)知識雷客。其他還有一些關(guān)于synchronized和volatile比較synchonrize和juc中的鎖比較
這里也簡單介紹一下:

  • volatile
    鎖提供了兩種主要特性:互斥(mutual exclusion)可見性(visibility)芒珠。
    • 互斥,即一次只允許一個線程持有某個特定的鎖搅裙,因此可使用該特性實現(xiàn)對共享數(shù)據(jù)的協(xié)調(diào)訪問協(xié)議皱卓,這樣,一次就只有一個線程能夠使用該共享數(shù)據(jù)部逮。
    • 可見性娜汁,它必須確保釋放鎖之前對共享數(shù)據(jù)做出的更改對于隨后獲得該鎖的另一個線程是可見的 —— 如果沒有同步機制提供的這種可見性保證,線程看到的共享變量可能是修改前的值或不一致的值甥啄,這將引發(fā)許多嚴重問題存炮。
      Volatile 變量具有 synchronized的可見性特性,Volatile是輕量級的synchronized蜈漓。

當且僅當下面條件全部滿足時, 才能使用volatile

  1. 對變量的寫入操作不依賴于變量的當前值, (++i/i++這種肯定不行), 或者能確保只有單個線程在更新
  1. 該變量不會與其他狀態(tài)變量一起納入不變性條件中
  2. 訪問變量時不需要加鎖
  • ReentrantLock
    ReentrantLock在內(nèi)存上的語義于synchronize相同, 但是它提供了額外的功能, 可以作為一種高級工具. 當需要一些 可定時, 可輪詢, 可中斷的鎖獲取操作, 或者希望使用公平鎖, 或者使用非塊結(jié)構(gòu)的編碼時 才應該考慮ReetrantLock穆桂。

以上就是這兩種鎖的比較的簡單介紹,想要深入學習的同學請大家自行搜索學習吧融虽。最后送給正在進行面試同學們的一句話:面試官虐我千百遍享完,我待面試官如初戀。---必須正能量有额,清噴般又。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市巍佑,隨后出現(xiàn)的幾起案子茴迁,更是在濱河造成了極大的恐慌,老刑警劉巖萤衰,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件堕义,死亡現(xiàn)場離奇詭異,居然都是意外死亡脆栋,警方通過查閱死者的電腦和手機倦卖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來椿争,“玉大人怕膛,你說我怎么就攤上這事∏刈伲” “怎么了褐捻?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵掸茅,是天一觀的道長。 經(jīng)常有香客問我柠逞,道長倦蚪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任边苹,我火速辦了婚禮,結(jié)果婚禮上裁僧,老公的妹妹穿的比我還像新娘个束。我一直安慰自己,他們只是感情好聊疲,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布茬底。 她就那樣靜靜地躺著,像睡著了一般获洲。 火紅的嫁衣襯著肌膚如雪阱表。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天贡珊,我揣著相機與錄音最爬,去河邊找鬼。 笑死门岔,一個胖子當著我的面吹牛爱致,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播寒随,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼糠悯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了妻往?” 一聲冷哼從身側(cè)響起互艾,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎讯泣,沒想到半個月后纫普,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡判帮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年局嘁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晦墙。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡悦昵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出晌畅,到底是詐尸還是另有隱情但指,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站棋凳,受9級特大地震影響拦坠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剩岳,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一贞滨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拍棕,春花似錦晓铆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蠢箩,卻和暖如春链蕊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谬泌。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工滔韵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掌实。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓奏属,卻偏偏與公主長得像,于是被迫代替她去往敵國和親潮峦。 傳聞我的和親對象是個殘疾皇子囱皿,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

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

  • 一、進程和線程 進程 進程就是一個執(zhí)行中的程序?qū)嵗类冢總€進程都有自己獨立的一塊內(nèi)存空間嘱腥,一個進程中可以有多個線程。...
    阿敏其人閱讀 2,612評論 0 13
  • 該文章轉(zhuǎn)自:http://blog.csdn.net/evankaka/article/details/44153...
    加來依藍閱讀 7,353評論 3 87
  • 寫在前面的話: 這篇博客是我從這里“轉(zhuǎn)載”的拘悦,為什么轉(zhuǎn)載兩個字加“”呢齿兔?因為這絕不是簡單的復制粘貼,我花了五六個小...
    SmartSean閱讀 4,732評論 12 45
  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,959評論 1 18
  • 本文主要講了java中多線程的使用方法础米、線程同步分苇、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應的一些線程函數(shù)用法屁桑、概述等医寿。 首先講...
    李欣陽閱讀 2,456評論 1 15