線程同步和線程死鎖

1.線程同步秃励,一個關(guān)鍵字:synchronized

為什么有這個東西呢傍念,假如有一個對象,里面有成員變量和方法股冗,如果有很多線程都想訪問它們霹陡,有可能造成用戶想避免的結(jié)果。

我也舉那個經(jīng)典的例子:假如你的銀行賬戶里面有2000塊錢止状,有一天你去銀行柜臺取錢烹棉,取1500,正在你辦理的時候怯疤,你老婆去了取款機浆洗,她也取錢,事先沒商量好誰取集峦,所以她也想取1500伏社。如果兩個人都取走了1500抠刺,合起來就3000了,銀行咋辦洛口?矫付??

我們把這個銀行賬戶當(dāng)作一個類來看待第焰,里面有一個錢的成員變量买优,有一個對錢的數(shù)量進行加減的方法,一個getMoney的方法挺举。

在柜臺取錢和在取款機取錢分別為2個線程杀赢。當(dāng)兩個線程同時訪問銀行賬戶這個類的對象的時候。都調(diào)用了錢的減法運算的方法湘纵,并通過getMoney方法拿到了1500塊錢脂崔,所有人都這樣干,于是梧喷,銀行破產(chǎn)了砌左。

解決方法,同步铺敌。

我在方法聲明的時候前面加一個synchronized關(guān)鍵字汇歹,public synchronized void method(){ },它代表的意思是在執(zhí)行這個方法的時候當(dāng)前對象被鎖定起來。

Java中的每個對象都有一個lock偿凭,當(dāng)訪問某個對象的synchronized方法時产弹,該對象就 會被上鎖(注意,是對象弯囊,不是方法痰哨,假如你在這個類中定義了多個方法,如果你的線程訪問到了其中的任意一個synchronized方法匾嘱,那么其它的就暫 時不能被訪問了斤斧,必須等到該對象被解鎖以后,即方法執(zhí)行結(jié)束才行)霎烙。解鎖的意思是值線程執(zhí)行該方法完畢折欠,或者說過程中拋出了異常。

再換一種說法吼过,就是,一個類中有synchronized方法咪奖,如果該類的對象的該方法被訪問時盗忱,那么整個該對象都被鎖定了,但是這個意思是其它非synchronized方法和成員變量還 是可以被訪問羊赵,注意區(qū)分這一點趟佃。因為synchronized方法會鎖定對象扇谣,所以一旦有一個synchronized方法被某個線程啟動了,那么對象已 經(jīng)被獨占了闲昭,其它的synchronized方法就不能再同時獨占對象了罐寨,但是普通方法和成員變量并不獨占對象,所以仍然可以被調(diào)用序矩。

需要注意的是鸯绿,如果同步方法里面有sleep方法,它仍然是同步方法的一部分簸淀,在它被執(zhí)行的過程中瓶蝴,鎖仍然不會被解開。

其實同步的意思就是上鎖租幕,同步方法舷手,進而達到對象上鎖的目的。假如有一個數(shù)據(jù)庫劲绪,有讀和修改2個方法男窟,你可以允許多個線程同時讀,但是你不能讓多個線程同時改贾富,所以說改的方法要同步歉眷,讀的方法不需要。(其實這里我更加覺得應(yīng)該同步的不是方法祷安,而是數(shù)據(jù)本身姥芥,只要有對象訪問對象,對象就應(yīng)該被鎖定汇鞭,避免讀的時候有對象要修改凉唐,修改的時候有對象要讀,甚至是多個對象同時都想改)霍骄。還有台囱,如果2個方法都修改了同一個值的話,那么2個方法都應(yīng)該加同步读整。

線程同步我覺得是這樣的簿训,你說概念吧,也還不難理解米间,我覺得真正難的是實際中的應(yīng)用强品,你必須考慮很多相關(guān)的問題,哪一個方法要同步屈糊,都需要好好琢磨的榛。

在這里說3個方法,wait逻锐,notify夫晌,notifyAll雕薪。

之前說過一個方法叫做sleep,通常來說你按照自己的經(jīng)驗和感覺要求線程睡眠一定的時間晓淀。但是所袁,有時候當(dāng)你不知道需要線程睡眠多久的時候,sleep方 法就不行了凶掰,必須使用wait燥爷。但是記住,wait只能用于同步方法锄俄。用法大概可以這樣局劲,比如你可以先進行一個while判斷(不推薦用if,假如有exception發(fā)生的話奶赠,就不再判斷直接執(zhí)行后面的鱼填,這樣可能還是有問題,所以最好用while毅戈,即使exception發(fā)生了苹丸,仍然會進行判斷),如果滿足一定條件就this.wait苇经,然后不滿足了就this.notify赘理。如果有很多同步方法的話,那么也可以使用notifyAll方法扇单,那么在這個對象上面等著的線程都會被叫醒商模。

synchronized關(guān)鍵字囊括了所有和同步有關(guān)的東西。除此之外蜘澜,還有一個關(guān)鍵字volatile施流,它只能用來同步基本類型的成員變量。數(shù)據(jù)的寫入 通常來說是通過緩存寫入內(nèi)存的鄙信,使用volatile的原理就是它會繞過緩存瞪醋,直接寫入內(nèi)存。讀取數(shù)據(jù)的時候同樣也直接從內(nèi)存讀取装诡,這樣就可以有效地避免 數(shù)據(jù)不同步的情況银受。

同步的幾個準則:

a.首先,盡量使得synchronized塊保持簡短鸦采。你鎖的東西越多宾巍,越可能造成死鎖。

b.不要在synchronized塊中調(diào)用那些可能引起阻塞的方法渔伯,比如read顶霞。

c.如果持有了鎖的話,不要對其它對象調(diào)用方法咱旱。

2.線程死鎖

既然可以上鎖确丢,那么假如有2個線程,一個線程想先鎖對象1吐限,再鎖對象2鲜侥,恰好另外有一個線程先鎖對象2,再鎖對象1诸典。

在這個過程中描函,當(dāng)線程1把對象1鎖好以后,就想去鎖對象2狐粱,但是不巧舀寓,線程2已經(jīng)把對象2鎖上了,也正在嘗試去鎖對象1肌蜻。

什么時候結(jié)束呢互墓,只有線程1把2個對象都鎖上并把方法執(zhí)行完,并且線程2把2個對象也都鎖上并且把方法執(zhí)行完畢蒋搜,那么就結(jié)束了篡撵,但是,誰都不肯放掉已經(jīng)鎖上的對象豆挽,所以就沒有結(jié)果育谬,這種情況就叫做線程死鎖。

其中一個解決方法就是加大鎖定的粒度帮哈,也就是盡量鎖大的對象膛檀,不要鎖得太小,還有盡量不要同時鎖2個或2個以上的對象娘侍,但是還有待于進一步研究咖刃。

3.wait和notify和notifyAll

主要是用來讓線程之間互相通知事件的發(fā)生。

1).wait

Object類中的final方法私蕾,有InterruptedException僵缺。它的作用是導(dǎo)致當(dāng)前的線程等待,直到其它線程調(diào)用此對象的notify方法或者notifyAll方法踩叭,wait還有一些重用方法磕潮,傳參數(shù),比如說時間長度容贝。

當(dāng)前的線程必須擁有此對象監(jiān)視器自脯,然后該線程發(fā)布對此監(jiān)視器的所有權(quán)并且開始等待,直到其它線程通過調(diào)用notify方法或者notifyAll方法斤富,通知在此對象的監(jiān)視器上等待的線程醒來膏潮,然后該線程將等到重新獲得對監(jiān)視器的所有權(quán)后才能開始執(zhí)行。

說說wait和sleep的區(qū)別

首先sleep

sleep是Thread里面的方法满力,在被執(zhí)行的時候焕参,鎖并不會被交出去轻纪,要直到sleep所在的方法全部被執(zhí)行完畢以后才交出鎖。

wait是Object里面的方法叠纷,在被執(zhí)行的時候刻帚,鎖被解除,由其它線程去爭奪涩嚣,直到有notify或者notifyAll方法喚醒它崇众。

2).Notify

也是Object類中的方法,用于喚醒在此對象上等待著的某一個線程航厚,如果有很多線程掛起的話顷歌,就隨機地決定哪一個。注意幔睬,是隨機的眯漩,這時可以用notifyAll來喚醒所有的。一定要注意這個問題溪窒,除非你明確地知道你在做什么坤塞,否則最好就是用notifyAll。

注意事項:

wait()和notify()必須包括在synchronized代碼塊中澈蚌,等待中的線程必須由notify()方法顯 式地喚醒摹芙,否則它會永遠地等待下去。很多人初級接觸多線程時宛瞄,會習(xí)慣把wait()和notify()放在run()方法里浮禾,一定要謹記,這兩個方法屬于 某個對象份汗,應(yīng)在對象所在的類方法中定義它盈电,然后run中去調(diào)用它。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末杯活,一起剝皮案震驚了整個濱河市匆帚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌旁钧,老刑警劉巖吸重,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異歪今,居然都是意外死亡嚎幸,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門寄猩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嫉晶,“玉大人,你說我怎么就攤上這事√娣希” “怎么了箍铭?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長椎镣。 經(jīng)常有香客問我坡疼,道長,這世上最難降的妖魔是什么衣陶? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮闸氮,結(jié)果婚禮上剪况,老公的妹妹穿的比我還像新娘。我一直安慰自己蒲跨,他們只是感情好译断,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著或悲,像睡著了一般孙咪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上巡语,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天翎蹈,我揣著相機與錄音,去河邊找鬼男公。 笑死荤堪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的枢赔。 我是一名探鬼主播澄阳,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼踏拜!你這毒婦竟也來了碎赢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤速梗,失蹤者是張志新(化名)和其女友劉穎肮塞,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體镀琉,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡峦嗤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了屋摔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烁设。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出装黑,到底是詐尸還是另有隱情副瀑,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布恋谭,位于F島的核電站糠睡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏疚颊。R本人自食惡果不足惜狈孔,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望材义。 院中可真熱鬧均抽,春花似錦、人聲如沸其掂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽款熬。三九已至深寥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贤牛,已是汗流浹背惋鹅。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留殉簸,地道東北人负饲。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像喂链,于是被迫代替她去往敵國和親返十。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

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