小話java多線程機(jī)制

寫作原因:對于并發(fā)編程一塊夜焦,是編程中的一道坎捞稿,對于它的理解有一定難度鳄厌。所以本文作者只能略作皮毛分享荞胡,對于深層學(xué)習(xí)仍在途中。希望讀者能夠多多交流

線程初識

先了解一下線程了嚎、進(jìn)程硝训、并發(fā)、并行的概念新思。進(jìn)程顧名思義窖梁,就是進(jìn)行中的程序,線程是進(jìn)程中可以獨(dú)立并發(fā)執(zhí)行的基本單元夹囚。進(jìn)程中包括內(nèi)存和線程兩塊纵刘,內(nèi)存是存儲資源,線程是進(jìn)程內(nèi)部各個(gè)功能的分載體荸哟,進(jìn)程內(nèi)所有線程都享有進(jìn)程的共享內(nèi)存假哎,此外線程有各自的獨(dú)立工作內(nèi)存。這些細(xì)節(jié)在下面的鎖機(jī)制中進(jìn)行分析鞍历。

創(chuàng)建

java中創(chuàng)建一個(gè)線程并不難舵抹,有下面兩種方式:直接使用Thread創(chuàng)建,實(shí)現(xiàn)Runnable接口然后注入Thread中創(chuàng)建劣砍。由于相對簡單惧蛹,這里不多加闡述。

生命周期

一個(gè)線程包括下面幾個(gè)生命周期:新建、可運(yùn)行(啟動線程)香嗓、運(yùn)行(系統(tǒng)調(diào)度)迅腔、阻塞/等待、消亡(退出run)靠娱。新建一個(gè)線程就是指我們寫完一個(gè)線程并將它實(shí)例化對象的過程沧烈,可運(yùn)行其實(shí)就是使用start()方法的過程,注意調(diào)用start()方法后不一定開始運(yùn)行像云,因?yàn)榫€程的運(yùn)行受到系統(tǒng)的調(diào)度锌雀。運(yùn)行過程是線程真正運(yùn)行的過程,當(dāng)調(diào)用sleep()迅诬、suspend()腋逆、wait()時(shí)或者線程執(zhí)行IO操作時(shí)會讓出CPU中止執(zhí)行,進(jìn)入阻塞和等待過程百框;當(dāng)run()方法結(jié)束后進(jìn)入死亡狀態(tài)闲礼。

常見API

這里介紹幾個(gè)常用的API:
類方法:currentThread()獲取當(dāng)前類對象、yield()線程禮讓铐维、sleep()線程休眠
setDaemon():設(shè)置守護(hù)線程(幽靈)柬泽。守護(hù)線程的特點(diǎn):當(dāng)其它線程中止時(shí),守護(hù)線程自動消亡嫁蛇。

線程數(shù)據(jù)共享問題

下面開始闡述線程同步的問題锨并。線程同步很重要,因?yàn)橐粋€(gè)進(jìn)程內(nèi)多個(gè)線程的數(shù)據(jù)經(jīng)常需要共享使用睬棚。然而如果在不知道任何關(guān)于線程同步的操作的情況下直接進(jìn)行線程間數(shù)據(jù)的共享第煮,那樣是很危險(xiǎn)的。為什么不能直接進(jìn)行線程之間的數(shù)據(jù)共享呢抑党?我們都知道每個(gè)線程有它們獨(dú)立的工作內(nèi)存包警,這說明線程操作共享內(nèi)存是間接的,也就是說某個(gè)線程對主工作內(nèi)存刷新后另一個(gè)工作內(nèi)存可能不知道底靠,那么你直接操作拿到的數(shù)據(jù)可能就過時(shí)了害晦,這樣共享就失敗了。此外暑中,由于多個(gè)線程可能同時(shí)進(jìn)行壹瘟,內(nèi)部操作某個(gè)共有的變量時(shí)順序可能會出現(xiàn)多種不同的順序,即指令重排序問題鳄逾。比如說A線程稻轨,B線程,如果A線程和B線程內(nèi)部多次操作C變量雕凹,這時(shí)就會出現(xiàn)混亂的排序問題殴俱。如果解決了以上兩個(gè)問題就解決了線程數(shù)據(jù)共享問題政冻。下面引入synchronized關(guān)鍵字。

解決方案

java提供了鎖機(jī)制(mutex)粱挡,每次只允許一個(gè)線程訪問一塊共享內(nèi)存赠幕。對于加鎖有兩種形式俄精,一種是使用代碼塊對某個(gè)共享的變量進(jìn)行加鎖询筏,另一種是直接對方法進(jìn)行加鎖,對方法進(jìn)行加鎖實(shí)際上是以成員方法所在的對象本身作為對象鎖竖慧。下面通過一個(gè)例子來認(rèn)識synchronized關(guān)鍵字:
Data類:

public class Data {
    static int i;
    public static synchronized void add(){
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        i++;
        System.out.println("i:"+i);
    }
}

ThreadA:

public class ThreadA extends Thread{
    private Data data;
    public ThreadA(String name,Data data){
        super(name);
        this.data = data;
    }
    public void run(){
        while(true){
            data.add();
        }

    }
}

Main.java:

public class Main {
    public static void main(String[] args){
        for(int i=0;i<10;i++){
            Data data = new Data();
            new ThreadA("Thread"+i,data).start();
        }
        Data data = new Data();
        while(true){
            data.add();
        }

    }

}

Main中新建了十個(gè)子線程嫌套,每個(gè)子線程中都可以執(zhí)行add()方法使i變量增大,我們使用synchronized關(guān)鍵字修飾add()靜態(tài)方法圾旨,就是表明Data類的類實(shí)例被用作對象鎖了踱讨。也就是data被鎖住了,其它線程操作data時(shí)只能一次一個(gè)操作砍的。所以如果你將synchronized關(guān)鍵字加在run()方法上就是無效的痹筛,因?yàn)檫@時(shí)鎖住的對象是線程對象,線程對象是多變的廓鞠,而非共享的區(qū)域帚稠。使用synchronized后線程執(zhí)行互斥代碼時(shí)大致過程是這樣的:先獲得互斥鎖,然后清空工作內(nèi)存床佳,從主內(nèi)存中拷貝變量的最新副本滋早,執(zhí)行代碼,然后將更改后的共享變量的值刷新到主內(nèi)存中砌们,最后釋放互斥鎖杆麸。這樣就實(shí)現(xiàn)了線程間共享數(shù)據(jù)邏輯。

總結(jié)

關(guān)于多線程這一大塊是硬骨頭浪感,很難真正把它啃下來昔头。文中還有許多地方?jīng)]有涉及,而且由于是個(gè)人理解可能存在疏漏影兽,后續(xù)在進(jìn)行Android線程剖析時(shí)再做補(bǔ)充揭斧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市赢笨,隨后出現(xiàn)的幾起案子未蝌,更是在濱河造成了極大的恐慌,老刑警劉巖茧妒,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萧吠,死亡現(xiàn)場離奇詭異,居然都是意外死亡桐筏,警方通過查閱死者的電腦和手機(jī)纸型,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狰腌,你說我怎么就攤上這事除破。” “怎么了琼腔?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵瑰枫,是天一觀的道長。 經(jīng)常有香客問我丹莲,道長光坝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任甥材,我火速辦了婚禮盯另,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好折欠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著芝发,像睡著了一般。 火紅的嫁衣襯著肌膚如雪俭令。 梳的紋絲不亂的頭發(fā)上后德,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天,我揣著相機(jī)與錄音抄腔,去河邊找鬼瓢湃。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赫蛇,可吹牛的內(nèi)容都是我干的绵患。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼悟耘,長吁一口氣:“原來是場噩夢啊……” “哼落蝙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起暂幼,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤筏勒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后旺嬉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體管行,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年邪媳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捐顷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荡陷。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖迅涮,靈堂內(nèi)的尸體忽然破棺而出废赞,到底是詐尸還是另有隱情,我是刑警寧澤叮姑,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布唉地,位于F島的核電站,受9級特大地震影響戏溺,放射性物質(zhì)發(fā)生泄漏渣蜗。R本人自食惡果不足惜屠尊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一旷祸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧讼昆,春花似錦托享、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至既峡,卻和暖如春羡榴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背运敢。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工校仑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人传惠。 一個(gè)月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓迄沫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親卦方。 傳聞我的和親對象是個(gè)殘疾皇子羊瘩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

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

  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司盼砍,掛了不少尘吗,但最終還是拿到小米、百度浇坐、阿里睬捶、京東、新浪吗跋、CVTE侧戴、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,254評論 11 349
  • Java8張圖 11宁昭、字符串不變性 12、equals()方法酗宋、hashCode()方法的區(qū)別 13积仗、...
    Miley_MOJIE閱讀 3,707評論 0 11
  • Java-Review-Note——4.多線程 標(biāo)簽: JavaStudy PS:本來是分開三篇的,后來想想還是整...
    coder_pig閱讀 1,653評論 2 17
  • 我是一個(gè)普洱茶受益者蜕猫,自從我與普洱結(jié)緣寂曹,帶動了身邊一大票親朋好友一起成為了普洱粉絲菌。 為什么我那么愛...
    國麗PollyZ閱讀 343評論 0 1
  • 這個(gè)時(shí)刻回右,應(yīng)該寫點(diǎn)什么隆圆,可有千言萬語又不知從何說起,慢慢醞釀著翔烁,把這一刻留在我的史記里渺氧,待到白發(fā)蒼蒼時(shí)好做回憶。 ...
    余淑萍閱讀 193評論 0 0