synchronized的作用?一、同步方法public synchronized void methodAAA(){
//….
}鎖定的是調(diào)用這個(gè)同步方法的對(duì)象
測試:a、不使用這個(gè)關(guān)鍵字修飾方法,兩個(gè)線程調(diào)用同一個(gè)對(duì)象的這個(gè)方法。目標(biāo)類:
線程類:
結(jié)果:輸出的數(shù)字交錯(cuò)在一起。說明不是同步的,兩個(gè)方法在不同的線程中是異步調(diào)用的。
b、修改目標(biāo)類,增加synchronized修飾
結(jié)果:輸出的數(shù)字是有序的,首先輸出A的數(shù)字,然后是B,說明是同步的,雖然是不同的線程,但兩個(gè)方法是同步調(diào)用的。注意:上面雖然是兩個(gè)不同的線程,但是是同一個(gè)實(shí)例對(duì)象。下面使用不同的實(shí)例對(duì)象進(jìn)行測試。
c、每個(gè)線程都有獨(dú)立的TestThread對(duì)象。目標(biāo)類:
結(jié)果:輸出的數(shù)字交錯(cuò)在一起。說明雖然增加了synchronized 關(guān)鍵字來修飾方法,但是不同的線程調(diào)用各自的對(duì)象實(shí)例,兩個(gè)方法仍然是異步的。
引申:對(duì)于這種多個(gè)實(shí)例,要想實(shí)現(xiàn)同步即輸出的數(shù)字是有序并且按線程先后順序輸出,我們可以增加一個(gè)靜態(tài)變量,對(duì)它進(jìn)行加鎖(后面將說明鎖定的對(duì)象)。
修改目標(biāo)類:
二、同步代碼塊
鎖定一個(gè)對(duì)象,其實(shí)鎖定的是該對(duì)象的引用(object reference)誰拿到這個(gè)鎖誰就可以運(yùn)行它所控制的那段代碼。當(dāng)有一個(gè)明確的對(duì)象作為鎖時(shí),就可以按上面的代碼寫程序,但當(dāng)沒有明確的對(duì)象作為鎖,只是想讓一段代碼同步時(shí),可以創(chuàng)建一個(gè)特殊的instance變量(它必須是一個(gè)對(duì)象)來充當(dāng)鎖(上面的解決方法就是增加了一個(gè)狀態(tài)鎖)。
a、鎖定一個(gè)對(duì)象,它不是靜態(tài)的private byte[] lock = new byte[0]; // 特殊的instance變量目標(biāo)類:
其實(shí)上面鎖定一個(gè)方法,等同于下面的:
b、鎖定一個(gè)對(duì)象或方法,它是靜態(tài)的這樣鎖定,它鎖定的是對(duì)象所屬的類public synchronized? static void execute(){??? //...}等同于
測試:
目標(biāo)類:
線程類:調(diào)用不同的方法,于是建立了兩個(gè)線程類
調(diào)用:
注意:1、用synchronized 來鎖定一個(gè)對(duì)象的時(shí)候,如果這個(gè)對(duì)象在鎖定代碼段中被修改了,則這個(gè)鎖也就消失了。看下面的實(shí)例:
說明:在reload和checkValid方法中都增加了synchronized關(guān)鍵字,對(duì)lock對(duì)象進(jìn)行加鎖。在不同線程中對(duì)同一個(gè)對(duì)象實(shí)例分別調(diào)用reload和checkValid方法。在reload方法中,不修改lock對(duì)象即注釋lock="abc"; ,結(jié)果在控制臺(tái)輸出reload end后才輸出100。說明是同步調(diào)用的。如果在reload方法中修改lock對(duì)象即去掉注釋,結(jié)果首先輸出了一個(gè)數(shù)字(當(dāng)前ve的大小),然后輸出reload end。說明是異步調(diào)用的。
2、單例模式中對(duì)多線程的考慮
說明:增加了一個(gè)內(nèi)部類,在內(nèi)部類中申明一個(gè)靜態(tài)的對(duì)象,實(shí)例化該單例類,初始化的數(shù)據(jù)都在單例類的構(gòu)造函數(shù)中進(jìn)行。這樣保證了多個(gè)實(shí)例同時(shí)訪問的時(shí)候,初始化的數(shù)據(jù)都已經(jīng)成功初始化了。