為什么說(shuō)synchronized是八面玲瓏呢,因?yàn)樗梢曰燠E在很多“場(chǎng)所”(方法,、代碼塊),,與各種角色(類(lèi)、對(duì)象)打交道,。 也正是因?yàn)樗陌嗣媪岘?,所以就顯得比較神秘,也比較復(fù)雜,今天就來(lái)追蹤下synchronized常去的地方和經(jīng)常搭訕的角色,。核心概念主要是介紹對(duì)象鎖和類(lèi)鎖,。 背景 synchronized,作為一種鎖,,主要是用于解決在多線程下的同步問(wèn)題,。 上篇中,我們?cè)诮榻B可見(jiàn)性的時(shí)候提到了java的內(nèi)存模型,,有主內(nèi)存和工作內(nèi)存,。 對(duì)應(yīng)到我們常見(jiàn)的堆、棧的理解是這樣的,。
在JVM中,每個(gè)對(duì)象和類(lèi)都會(huì)與一個(gè)監(jiān)聽(tīng)器關(guān)聯(lián),,為了實(shí)現(xiàn)監(jiān)聽(tīng)器的排他監(jiān)視能力,,每個(gè)對(duì)象和類(lèi)都會(huì)關(guān)聯(lián)一個(gè)鎖。當(dāng)某個(gè)線程獲取了某個(gè)對(duì)象的鎖,,則由于排他性,,其他線程就會(huì)阻塞等待獲取鎖以獲取執(zhí)行權(quán)。 每個(gè)對(duì)象都只有唯一一個(gè)鎖,,同一時(shí)間,,也只有一個(gè)線程可以擁有該鎖。 類(lèi)鎖,,其實(shí)可以理解為一種特殊的對(duì)象鎖,,因?yàn)樵贘VM并不存在所謂的類(lèi)鎖。 當(dāng)JVM加載某個(gè)class時(shí),,加在這個(gè)Class對(duì)象上的就是類(lèi)鎖,。所有該類(lèi)的實(shí)例共享這個(gè)類(lèi)鎖,當(dāng)某對(duì)象獲取類(lèi)鎖權(quán)限時(shí),則對(duì)于所有靜態(tài)方法具有相同的執(zhí)行權(quán),。 使用synchronized和未使用synchronized的對(duì)比 1,、 不使用synchronized
最后的執(zhí)行結(jié)果如下 注意: 這里有一個(gè)可見(jiàn)性的思考。當(dāng)我們?nèi)绻麤](méi)有接觸或者不了解可見(jiàn)性這個(gè)概念之前,,我們想當(dāng)然的認(rèn)為T(mén)hreadA和ThreadB都是操作了num變量,,那么對(duì)于同一個(gè)變量操作肯定最終都是保持一致的,所以都是num=200,。 其實(shí)這里的num變量是共享變量,,所以會(huì)存在被覆蓋的情況。如果這個(gè)num變量是聲明在addI(String username)方法里面,,那么這時(shí)候鑒于可見(jiàn)性,,雖然都是操作num,但是每個(gè)線程都持有自己的num副本,,所以最后的結(jié)果是這樣的
2,、使用synchronized 上面的例子是沒(méi)有使用synchronized的情況,如果加上synchronized關(guān)鍵字,,這時(shí)候相當(dāng)于在addI()方法上加鎖了,,更準(zhǔn)確的說(shuō)是在HasSelfPrivateNum類(lèi)的實(shí)例化對(duì)象上獲取了對(duì)象鎖。 鑒于一個(gè)對(duì)象在同一時(shí)間只能被一個(gè)線程占有,,所以當(dāng)ThreadA進(jìn)入方法后,,會(huì)一直執(zhí)行知道結(jié)束,即使這里有休眠2秒鐘,,ThreadB只能乖乖的等ThreadA執(zhí)行完才能獲取執(zhí)行權(quán)繼續(xù)執(zhí)行,。最終執(zhí)行結(jié)果如下 synchronized使用的四種同步場(chǎng)景 synchronized使用場(chǎng)景主要包括如下四種同步場(chǎng)景
1、實(shí)例方法 參見(jiàn)上面對(duì)比例子中“加synchronized”的情況 2,、靜態(tài)方法 執(zhí)行結(jié)果如下
這里的synchronized是加載靜態(tài)方法上的,,我們知道靜態(tài)方法是通過(guò)類(lèi)直接調(diào)用的,,不需要實(shí)例化的。這里用的就是類(lèi)鎖,,也就是類(lèi)的Class對(duì)象的鎖,,所以這里兩個(gè)線程在同一時(shí)間也只會(huì)有一個(gè)獲取到該類(lèi)鎖從而獲得執(zhí)行權(quán)。 3,、實(shí)例方法中的同步塊 直接看代碼 執(zhí)行結(jié)果如下
這里的this就是ObjectService類(lèi)的實(shí)例化對(duì)象,,因?yàn)橐粋€(gè)對(duì)象只有一個(gè)對(duì)象鎖,所以這里可以保證同步,,只有前一個(gè)線程執(zhí)行完后,,后一個(gè)線程才有機(jī)會(huì)執(zhí)行。 4,、靜態(tài)方法中的同步塊 參見(jiàn)2和3,,只是在靜態(tài)方法內(nèi)部加上synchronized。本質(zhì)還是類(lèi)鎖,。 文中肯定有理解偏差的地方,,寫(xiě)博客的好處就是,本來(lái)已經(jīng)認(rèn)為理所當(dāng)然的地方,,當(dāng)需要一字一句寫(xiě)出來(lái)的時(shí)候,,就會(huì)加深思考一些問(wèn)題的細(xì)節(jié),。 好比文中沒(méi)有加synchronized的例子,,突然想到可見(jiàn)性,又想到主內(nèi)存和工作內(nèi)存以及堆棧之類(lèi)的內(nèi)存結(jié)構(gòu),,雖然一度被繞暈,,查了兩小時(shí)的資料,最終也算是找了一套理論勉強(qiáng)把自己說(shuō)服,。 如果您覺(jué)得閱讀本文對(duì)您有幫助,,請(qǐng)點(diǎn)一下“關(guān)注”按鈕,您的“關(guān)注”將是我最大的寫(xiě)作動(dòng)力,! |
|
來(lái)自: 太極混元天尊 > 《學(xué)習(xí)資料》