java鎖機(jī)制

實(shí)戰(zhàn)才是硬道理彻磁,說(shuō)教有些虛守伸,不玩虛的。先讓我們看一個(gè)例子:創(chuàng)建一個(gè)線程類育八,實(shí)現(xiàn)在控制臺(tái)打印數(shù)字從0到9999补箍。然后同時(shí)開(kāi)啟10個(gè)線程改执,查看打印結(jié)果啸蜜;

程序清單1-1

程序清單1-1,其實(shí)就是讓10個(gè)線程在控制臺(tái)上數(shù)數(shù)辈挂,從0數(shù)到9999衬横。理想情況下,我們希望看到一個(gè)線程數(shù)完终蒂,然后另一個(gè)線程才開(kāi)始數(shù)蜂林。但是控制臺(tái)打印的順序告訴我們,這10個(gè)線程是亂糟糟的在那里搶著數(shù)拇泣,絲毫沒(méi)有任何規(guī)矩可言噪叙。

如何才能在理想情況下每個(gè)線程依次打印數(shù)字呢?引入了多線程編程技術(shù)霉翔。

Java多線程編程中睁蕾,關(guān)鍵字synchronized是繞不開(kāi)的。但是很多人看到這個(gè)東西會(huì)感到困惑:“都說(shuō)同步機(jī)制是通過(guò)對(duì)象鎖來(lái)實(shí)現(xiàn)的债朵,但是這么一個(gè)關(guān)鍵字子眶,我也看不出來(lái)Java程序鎖住了哪個(gè)對(duì)象啊序芦?”讓我們使用synchronized關(guān)鍵字來(lái)修飾run()方法看看效果如何臭杰。

程序清單1-2

執(zhí)行程序,查看控制臺(tái)打印順序谚中,打印順序依然亂糟糟的渴杆,程序清單1-1與程序清單1-2并沒(méi)有區(qū)別∠芩“我已經(jīng)使用synchronized來(lái)同步run()方法了啊将塑, 哪里出錯(cuò)了呢?”

我們?cè)僭囍薷南鲁绦蝌螋铮瑂ynchronized同步run()方法中的代碼塊。

程序清單1-3

執(zhí)行程序艾疟,查看控制臺(tái)打印順序来吩,我們看到了預(yù)期的效果:10個(gè)線程不再是爭(zhēng)先恐后的報(bào)數(shù)了,而是一個(gè)接一個(gè)的報(bào)數(shù)蔽莱。對(duì)比程序清單1-3跟1-2弟疆,程序清單1-3在main方法啟動(dòng)10個(gè)線程之前,創(chuàng)建了一個(gè)String類型的對(duì)象盗冷。并通過(guò)ThreadTest的構(gòu)造函數(shù)怠苔,將這個(gè)對(duì)象賦值給每一個(gè)ThreadTest線程對(duì)象中的私有變量lock。根據(jù)Java方法的傳值特點(diǎn)仪糖,我們知道柑司,這些線程的lock變量實(shí)際上指向的是堆內(nèi)存中的同一個(gè)內(nèi)存區(qū)域迫肖,即存放main函數(shù)中的lock變量的區(qū)域。程序清單1-2攒驰,對(duì)于一個(gè)成員方法加synchronized關(guān)鍵字蟆湖,這實(shí)際上是以這個(gè)成員方法所在的對(duì)象本身作為對(duì)象鎖的,創(chuàng)建多少個(gè)對(duì)象就有多少個(gè)對(duì)象鎖玻粪,每個(gè)對(duì)象鎖只對(duì)該對(duì)象起作用隅津。一共十個(gè)線程,每個(gè)線程持有自己線程對(duì)象的那個(gè)對(duì)象鎖劲室。這必然不能產(chǎn)生同步的效果伦仍。換句話說(shuō),如果要對(duì)這些線程進(jìn)行同步很洋,那么這些線程所持有的對(duì)象鎖應(yīng)當(dāng)是共享且唯一的充蓝!

>>對(duì)象鎖

可以這樣理解,每個(gè)實(shí)例對(duì)象僅有一把鎖蹲缠,把對(duì)象看作一間房子棺克,哪個(gè)線程先拿到鎖就進(jìn)入房間中,其他線程在門外等待房間中線程出來(lái)才能進(jìn)入房間线定。

對(duì)象鎖又稱之為內(nèi)置鎖娜谊。除了對(duì)象鎖還有類鎖。

>>類鎖

程序中通過(guò)類可以創(chuàng)建多個(gè)實(shí)例對(duì)象斤讥,但每個(gè)類只有一個(gè)類實(shí)例纱皆,JVM類加載完成,每個(gè)類在方法區(qū)只存在一份芭商,方法區(qū)是內(nèi)存共享的派草。所以類鎖只有一個(gè)。

使用類鎖來(lái)實(shí)現(xiàn)程序

程序清單1-4

通過(guò)程序清單1-2铛楣,我們清楚的了解到對(duì)于一個(gè)成員方法加synchronized關(guān)鍵字近迁,這實(shí)際上是以這個(gè)成員方法所在的對(duì)象本身作為對(duì)象鎖。在本例中簸州,我們以ThreadTest類實(shí)例作為鎖鉴竭,全局唯一。

我們以另一種類鎖的方式來(lái)實(shí)現(xiàn)程序

程序清單1-5

你們應(yīng)該很困惑:這里synchronized靜態(tài)方法是用什么來(lái)做對(duì)象鎖的呢岸浑?

我們知道搏存,對(duì)于同步靜態(tài)方法,對(duì)象鎖就是該靜態(tài)方法所在的類的Class實(shí)例矢洲,由于在JVM中璧眠,所有被加載的類都有唯一的類實(shí)例,具體到本例,就是唯一的 ThreadTest3.class對(duì)象责静。不管我們創(chuàng)建了該類的多少實(shí)例袁滥,但是它的類實(shí)例仍然是一個(gè)!

這樣我們就知道了:

1泰演、對(duì)于同步的方法或者代碼塊來(lái)說(shuō)呻拌,必須獲得對(duì)象鎖才能夠進(jìn)入同步方法或者代碼塊進(jìn)行操作;

2睦焕、如果采用函數(shù)或方法級(jí)別的同步藐握,則對(duì)象鎖即為函數(shù)或方法所在的對(duì)象,如果是靜態(tài)方法垃喊,對(duì)象鎖即指 函數(shù)哦或方法所在的Class對(duì)象(唯一)猾普;

3、對(duì)于代碼塊本谜,synchronized(abc)中的內(nèi)置鎖即為abc對(duì)象鎖初家;

4、因?yàn)榈谝环N情況乌助,對(duì)象鎖即為每一個(gè)線程對(duì)象溜在,因此有多個(gè),所以同步失效他托,第二種共用同一個(gè)對(duì)象lock鎖掖肋,因此同步生效,第三個(gè)因?yàn)槭峭届o態(tài)方法赏参,因此鎖住的是ThreadTest3.class志笼,因此同步生效。

如上述正確把篓,則同步有兩種方式纫溃,同步代碼塊和同步函數(shù)或方法(為什么沒(méi)有wait和notify?這個(gè)我會(huì)在補(bǔ)充章節(jié)中做出闡述)

如果是同步代碼塊韧掩,則鎖住的對(duì)象需要編程人員自己指定紊浩,一般有些代碼為synchronized(this)只有在單態(tài)模式才生效(類的實(shí)例有任何時(shí)候僅有一個(gè));

如果是同步函數(shù)或方法疗锐,則分靜態(tài)和非靜態(tài)兩種坊谁。

靜態(tài)方法則一定會(huì)同步,非靜態(tài)方法在單例模式才生效窒悔,推薦用靜態(tài)方法(不用擔(dān)心是否單例)。

所以說(shuō)敌买,在Java多線程編程中简珠,關(guān)鍵字synchronized最常見(jiàn)的用法是依靠對(duì)象鎖的機(jī)制來(lái)實(shí)現(xiàn)線程同步的。

JVM邏輯內(nèi)存模型

JVM邏輯內(nèi)存模型
虛擬機(jī)內(nèi)存模型中定義的訪問(wèn)操作

寄存器:這是最快的存儲(chǔ)區(qū),因?yàn)樗挥诓煌谄渌鎯?chǔ)區(qū)的地方--處理器內(nèi)部聋庵。但是寄存器的數(shù)量機(jī)器有限膘融,所以寄存器根據(jù)需求進(jìn)行分配。你不能直接控制祭玉,也不能在程序中直接感覺(jué)到它的存在任何跡象氧映。

堆棧:位于通用RAM(隨機(jī)訪問(wèn)存儲(chǔ)器)中,但通過(guò)“堆棧指針”可以從處理器那里獲得直接支持脱货。堆棧指針若向下移動(dòng)岛都,則分配新的內(nèi)存;若向上移動(dòng)振峻,則釋放那些內(nèi)存臼疫。這是一種快速有效的分配存儲(chǔ)方法,僅次于寄存器扣孟。創(chuàng)建程序時(shí)烫堤,Java系統(tǒng)必須知道存儲(chǔ)在堆棧內(nèi)的所有項(xiàng)的確切生命周期,以便上下移動(dòng)堆棧指針凤价。這一約束限制了程序的靈活性鸽斟,所以雖然某些Java數(shù)據(jù)存儲(chǔ)與堆棧中----特別是對(duì)象引用,但是Java對(duì)象卻不存在堆棧中利诺;

:一種通用的內(nèi)存池(位于RAM區(qū))富蓄,用于存放所有的Java對(duì)象。堆不同于堆棧的好處是:編譯器不需要知道存儲(chǔ)的數(shù)據(jù)在堆中存活多長(zhǎng)時(shí)間立轧。因此格粪,堆里分配對(duì)象有很大的靈活性。當(dāng)需要一個(gè)對(duì)象時(shí)氛改,只需要new寫一行簡(jiǎn)單的代碼帐萎,當(dāng)執(zhí)行這段代碼時(shí),會(huì)自動(dòng)在堆里進(jìn)行存儲(chǔ)分配胜卤。當(dāng)然疆导,為這種靈活性要付出代價(jià):用堆進(jìn)行內(nèi)存分配和清理可能比用堆棧進(jìn)行內(nèi)存分配和清理需要更長(zhǎng)的時(shí)間。

常量存儲(chǔ):常量直接存放在程序代碼內(nèi)部葛躏,這樣做是安全的澈段,因?yàn)樗麄冇肋h(yuǎn)不會(huì)被改變。有時(shí)候舰攒,在嵌入式系統(tǒng)中败富,常量本身會(huì)和其他部分分離開(kāi),在這種情況下摩窃,常量可以存放在ROM(只讀存儲(chǔ)器)中兽叮。

非RAM存儲(chǔ):如果數(shù)據(jù)完全存活在程序之外芬骄,那么它可以完全不受程序的任何控制,在程序沒(méi)有運(yùn)行時(shí)也可以存在鹦聪。比較基本的兩個(gè)例子是“流對(duì)象”和“持久化對(duì)象”账阻。流對(duì)象中,對(duì)象轉(zhuǎn)換成字節(jié)流泽本,通暢被發(fā)送到另一臺(tái)機(jī)器淘太。在“持久化”對(duì)象中,對(duì)象被存在磁盤上规丽,因此蒲牧,及時(shí)程序終止,數(shù)據(jù)也可以保持自己的狀態(tài)嘁捷。這種存儲(chǔ)的技巧在于:把對(duì)象轉(zhuǎn)換成可以在其他媒介上存儲(chǔ)的事務(wù)造成,在需要的時(shí)候,可以恢復(fù)成常規(guī)的雄嚣,基于RAM的對(duì)象晒屎。比如Java中輕量級(jí)的JDBC和Hibernate這樣的機(jī)制提供支持。

Java創(chuàng)建對(duì)象的存儲(chǔ)方式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缓升,一起剝皮案震驚了整個(gè)濱河市鼓鲁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌港谊,老刑警劉巖骇吭,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異歧寺,居然都是意外死亡燥狰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門斜筐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)龙致,“玉大人,你說(shuō)我怎么就攤上這事顷链∧看” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵嗤练,是天一觀的道長(zhǎng)榛了。 經(jīng)常有香客問(wèn)我,道長(zhǎng)煞抬,這世上最難降的妖魔是什么霜大? 我笑而不...
    開(kāi)封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮革答,結(jié)果婚禮上战坤,老公的妹妹穿的比我還像新娘遮婶。我一直安慰自己,他們只是感情好湖笨,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蹦骑,像睡著了一般慈省。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上眠菇,一...
    開(kāi)封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天边败,我揣著相機(jī)與錄音,去河邊找鬼捎废。 笑死笑窜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的登疗。 我是一名探鬼主播排截,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼辐益!你這毒婦竟也來(lái)了断傲?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤智政,失蹤者是張志新(化名)和其女友劉穎认罩,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體续捂,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡垦垂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了牙瓢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片劫拗。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖一罩,靈堂內(nèi)的尸體忽然破棺而出杨幼,到底是詐尸還是另有隱情,我是刑警寧澤聂渊,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布差购,位于F島的核電站,受9級(jí)特大地震影響汉嗽,放射性物質(zhì)發(fā)生泄漏欲逃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一饼暑、第九天 我趴在偏房一處隱蔽的房頂上張望稳析。 院中可真熱鬧洗做,春花似錦、人聲如沸彰居。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)陈惰。三九已至畦徘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抬闯,已是汗流浹背井辆。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溶握,地道東北人杯缺。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像睡榆,于是被迫代替她去往敵國(guó)和親萍肆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法胀屿,類相關(guān)的語(yǔ)法匾鸥,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法碉纳,異常的語(yǔ)法勿负,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,664評(píng)論 18 399
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司劳曹,掛了不少奴愉,但最終還是拿到小米、百度铁孵、阿里锭硼、京東、新浪蜕劝、CVTE檀头、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,277評(píng)論 11 349
  • (一)Java部分 1、列舉出JAVA中6個(gè)比較常用的包【天威誠(chéng)信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,114評(píng)論 0 62
  • 很多人都知道岖沛,在Java多線程編程中暑始,有一個(gè)重要的關(guān)鍵字Synchronized。但是很多人看到這個(gè)東西會(huì)感到困惑...
    Ten_Minutes閱讀 474評(píng)論 0 2
  • 作為一只大一狗婴削,在一次出演某個(gè)晚會(huì)時(shí)廊镜,在后臺(tái)化妝,看到其他妹紙分分鐘各種眼線眼影唉俗,不禁發(fā)現(xiàn)我除了會(huì)畫個(gè)眉毛涂個(gè)睫毛...
    千焦每摩爾閱讀 562評(píng)論 1 3