中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

淄博晨曦網(wǎng)站建設2023年新聞熱點事件

淄博晨曦網(wǎng)站建設,2023年新聞熱點事件,西安網(wǎng)站建設公司都有哪些,開發(fā)軟件用什么編程軟件synchronized的三種使用方式 **1.修飾實例方法,**作用于當前實例加鎖,進入同步代碼前要獲得當前實例的鎖。 沒有問題的寫法: public class AccountingSync implements Runnable{//共享資源(臨界資源)static int i0;/*** synchronized 修飾實例方法*/p…

synchronized的三種使用方式

**1.修飾實例方法,**作用于當前實例加鎖,進入同步代碼前要獲得當前實例的鎖。

沒有問題的寫法:

public class AccountingSync implements Runnable{//共享資源(臨界資源)static int i=0;/*** synchronized 修飾實例方法*/public synchronized void increase(){i++;}@Overridepublic void run() {for(int j=0;j<1000000;j++){increase();}}public static void main(String[] args) throws InterruptedException {AccountingSync instance=new AccountingSync();Thread t1=new Thread(instance);Thread t2=new Thread(instance);t1.start();t2.start();t1.join();t2.join();System.out.println(i);}/*** 輸出結(jié)果:* 2000000*/
}

因為這段代碼中只輸入了一個AccountingSync實例。

下面是有問題的寫法:

public class AccountingSyncBad implements Runnable{static int i=0;public synchronized void increase(){i++;}@Overridepublic void run() {for(int j=0;j<1000000;j++){increase();}}public static void main(String[] args) throws InterruptedException {//new新實例Thread t1=new Thread(new AccountingSyncBad());//new新實例Thread t2=new Thread(new AccountingSyncBad());t1.start();t2.start();//join含義:當前線程A等待thread線程終止之后才能從thread.join()返回t1.join();t2.join();System.out.println(i);}
}

在上述代碼中出現(xiàn)了一個嚴重的錯誤,雖然我們使用了sychronized修飾了increase方法,但new了兩個不同的實例對象,這就意味著會出現(xiàn)兩個不同的實例對象鎖,這樣的話ti和t2都會進入各自的對象鎖,因此線程安全就得不到保證。想要解決這個問題,就需要將sychronized作用于靜態(tài)的increase方法。

2.修飾靜態(tài)方法,作用于當前類對象加鎖,進入同步代碼前要獲得當前類對象的鎖。

當sychronized使用靜態(tài)方法時,對象鎖就會是當前類的class對象鎖。因為靜態(tài)成員不屬于任何一個實例對象,所以通過class對象鎖可以控制靜態(tài) 成員的并發(fā)操作。

如果一個線程A調(diào)用一個實例對象的非static synchronized方法,而線程B需要調(diào)用這個實例對象所屬類的靜態(tài) synchronized方法,是允許的,不會發(fā)生互斥現(xiàn)象,因為訪問靜態(tài) synchronized 方法占用的鎖是當前類的class對象,而訪問非靜態(tài) synchronized 方法占用的鎖是當前實例對象鎖,看如下代碼:

public class AccountingSyncClass implements Runnable{static int i=0;/*** 作用于靜態(tài)方法,鎖是當前class對象,也就是* AccountingSyncClass類對應的class對象*/public static synchronized void increase(){i++;}/*** 非靜態(tài),訪問時鎖不一樣不會發(fā)生互斥*/public synchronized void increase4Obj(){i++;}@Overridepublic void run() {for(int j=0;j<1000000;j++){increase();}}public static void main(String[] args) throws InterruptedException {//new新實例Thread t1=new Thread(new AccountingSyncClass());//new心事了Thread t2=new Thread(new AccountingSyncClass());//啟動線程t1.start();t2.start();t1.join();t2.join();System.out.println(i);}
}

這種情況下可能會發(fā)現(xiàn)線程安全問題(操作了共享靜態(tài)變量i)。

3.修飾代碼塊,指定加鎖對象,對給定對象加鎖,進入同步代碼庫前要獲得給定對象的鎖。

synchronized同步代碼塊

public class AccountingSync implements Runnable{static AccountingSync instance=new AccountingSync();static int i=0;@Overridepublic void run() {//省略其他耗時操作....//使用同步代碼塊對變量i進行同步操作,鎖對象為instancesynchronized(instance){for(int j=0;j<1000000;j++){i++;}}}public static void main(String[] args) throws InterruptedException {Thread t1=new Thread(instance);Thread t2=new Thread(instance);t1.start();t2.start();t1.join();t2.join();System.out.println(i);}
}

當然除了instance作為對象外,我們還可以使用this對象(代表當前實例)或者當前類的class對象作為鎖,如下代碼:

//this,當前實例對象鎖
synchronized(this){for(int j=0;j<1000000;j++){i++;}
}//class對象鎖
synchronized(AccountingSync.class){for(int j=0;j<1000000;j++){i++;}
}

synchronized底層語義原理

Java 虛擬機中的同步(Synchronization)基于進入和退出管程(Monitor)對象實現(xiàn), 無論是顯式同步(有明確的 monitorenter 和 monitorexit 指令,即同步代碼塊)還是隱式同步都是如此。

同步方法 并不是由 monitorenter 和 monitorexit 指令來實現(xiàn)同步的,而是由方法調(diào)用指令讀取運行時常量池中方法的 ACC_SYNCHRONIZED 標志來隱式實現(xiàn)的

理解Java對象頭與Monitor

在JVM中,對象在內(nèi)存中的布局分為三塊區(qū)域:對象頭、實例數(shù)據(jù)和對齊填充。
?
在這里插入圖片描述
實例變量:存放類的屬性數(shù)據(jù)信息,包括父類的屬性信息,如果是數(shù)組的實例部分還包括數(shù)組的長度,這部分內(nèi)存按4字節(jié)對齊。

填充數(shù)據(jù):由于虛擬機要求對象起始地址必須是8字節(jié)的整數(shù)倍。填充數(shù)據(jù)不是必須存在的,僅僅是為了字節(jié)對齊

頂部,則是Java頭對象,它實現(xiàn)synchronized的鎖對象的基礎。

synchronized使用的鎖對象是存儲在Java對象頭里的,jvm中采用2個字來存儲對象頭(如果對象是數(shù)組則會分配3個字,多出來的1個字記錄的是數(shù)組長度),其主要結(jié)構是由Mark Word 和 Class Metadata Address 組成,其結(jié)構說明如下表:
?
在這里插入圖片描述

其中Mark Word在默認情況下存儲著對象的HashCode、分代年齡、鎖標記位等以下是32位JVM的Mark Word默認存儲結(jié)構
在這里插入圖片描述

由于對象頭的信息是與對象自身定義的數(shù)據(jù)沒有關系的額外存儲成本,因此考慮到JVM的空間效率,Mark Word 被設計成為一個非固定的數(shù)據(jù)結(jié)構,以便存儲更多有效的數(shù)據(jù),它會根據(jù)對象本身的狀態(tài)復用自己的存儲空間,如32位JVM下,除了上述列出的Mark Word默認存儲結(jié)構外,還有如下可能變化的結(jié)構:
在這里插入圖片描述
主要分析一下重量級鎖也就是通常說synchronized的對象鎖,鎖標識位為10,其中指針指向的是monitor對象(也稱為管程或監(jiān)視器鎖)的起始地址。每個對象都存在著一個 monitor 與之關聯(lián),對象與其 monitor 之間的關系有存在多種實現(xiàn)方式,如monitor可以與對象一起創(chuàng)建銷毀或當線程試圖獲取對象鎖時自動生成,但當一個 monitor 被某個線程持有后,它便處于鎖定狀態(tài)。

在Java虛擬機(HotSpot)中,monitor是由ObjectMonitor實現(xiàn)的,其主要數(shù)據(jù)結(jié)構如下(位于HotSpot虛擬機源碼ObjectMonitor.hpp文件,C++實現(xiàn)的)。

ObjectMonitor() {_header       = NULL;_count        = 0; //記錄個數(shù)_waiters      = 0,_recursions   = 0;_object       = NULL;_owner        = NULL;_WaitSet      = NULL; //處于wait狀態(tài)的線程,會被加入到_WaitSet_WaitSetLock  = 0 ;_Responsible  = NULL ;_succ         = NULL ;_cxq          = NULL ;FreeNext      = NULL ;_EntryList    = NULL ; //處于等待鎖block狀態(tài)的線程,會被加入到該列表_SpinFreq     = 0 ;_SpinClock    = 0 ;OwnerIsThread = 0 ;}

ObjectMonitor中有兩個隊列,_WaitSet 和 _EntryList,用來保存ObjectWaiter對象列表( 每個等待鎖的線程都會被封裝成ObjectWaiter對象),_owner指向持有ObjectMonitor對象的線程,當多個線程同時訪問一段同步代碼時,首先會進入 _EntryList 集合,當線程獲取到對象的monitor 后進入 _Owner 區(qū)域并把monitor中的owner變量設置為當前線程同時monitor中的計數(shù)器count加1,若線程調(diào)用 wait() 方法,將釋放當前持有的monitor,owner變量恢復為null,count自減1,同時該線程進入 WaitSet集合中等待被喚醒。若當前線程執(zhí)行完畢也將釋放monitor(鎖)并復位變量的值,以便其他線程進入獲取monitor(鎖)。
?
在這里插入圖片描述

monitor對象存在于每個Java對象的對象頭中(存儲的指針的指向),synchronized鎖便是通過這種方式獲取鎖的,也是為什么Java中任意對象可以作為鎖的原因,同時也是notify/notifyAll/wait等方法存在于頂級對象Object中的原因。

synchronized代碼塊底層原理

現(xiàn)在我們重新定義一個synchronized修飾的同步代碼塊,在代碼塊中操作共享變量i,如下:

public class SyncCodeBlock {public int i;public void syncTask(){//同步代碼庫synchronized (this){i++;}}
}

編譯上述代碼并使用javap反編譯后得到字節(jié)碼如下(這里我們省略一部分沒有必要的信息):

Classfile /Users/zejian/Downloads/Java8_Action/src/main/java/com/zejian/concurrencys/SyncCodeBlock.classLast modified 2017-6-2; size 426 bytesMD5 checksum c80bc322c87b312de760942820b4fed5Compiled from "SyncCodeBlock.java"
public class com.zejian.concurrencys.SyncCodeBlockminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool://........省略常量池中數(shù)據(jù)//構造函數(shù)public com.zejian.concurrencys.SyncCodeBlock();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 7: 0//===========主要看看syncTask方法實現(xiàn)================public void syncTask();descriptor: ()Vflags: ACC_PUBLICCode:stack=3, locals=3, args_size=10: aload_01: dup2: astore_13: monitorenter  //注意此處,進入同步方法4: aload_05: dup6: getfield      #2             // Field i:I9: iconst_110: iadd11: putfield      #2            // Field i:I14: aload_115: monitorexit   //注意此處,退出同步方法16: goto          2419: astore_220: aload_121: monitorexit //注意此處,退出同步方法22: aload_223: athrow24: returnException table://省略其他字節(jié)碼.......
}
SourceFile: "SyncCodeBlock.java"

我們主要關注字節(jié)碼中的如下代碼

3: monitorenter  //進入同步方法
//..........省略其他  
15: monitorexit   //退出同步方法
16: goto          24
//省略其他.......
21: monitorexit //退出同步方法

從字節(jié)碼中可知同步語句塊的實現(xiàn)使用的是monitorenter 和 monitorexit 指令,其中monitorenter指令指向同步代碼塊的開始位置,monitorexit指令則指明同步代碼塊的結(jié)束位置,當執(zhí)行monitorenter指令時,當前線程將試圖獲取 objectref(即對象鎖) 所對應的 monitor 的持有權,當 objectref 的 monitor 的進入計數(shù)器為 0,那線程可以成功取得 monitor,并將計數(shù)器值設置為 1,取鎖成功。**如果當前線程已經(jīng)擁有 objectref 的 monitor 的持有權,那它可以重入這個 monitor (關于重入性稍后會分析),重入時計數(shù)器的值也會加 1。**倘若其他線程已經(jīng)擁有 objectref 的 monitor 的所有權,那當前線程將被阻塞,直到正在執(zhí)行線程執(zhí)行完畢,即monitorexit指令被執(zhí)行,執(zhí)行線程將釋放 monitor(鎖)并設置計數(shù)器值為0 ,其他線程將有機會持有 monitor 。值得注意的是編譯器將會確保無論方法通過何種方式完成,方法中調(diào)用過的每條 monitorenter 指令都有執(zhí)行其對應 monitorexit 指令,而無論這個方法是正常結(jié)束還是異常結(jié)束。為了保證在方法異常完成時 monitorenter 和 monitorexit 指令依然可以正確配對執(zhí)行,編譯器會自動產(chǎn)生一個異常處理器,這個異常處理器聲明可處理所有的異常,它的目的就是用來執(zhí)行 monitorexit 指令。從字節(jié)碼中也可以看出多了一個monitorexit指令,它就是異常結(jié)束時被執(zhí)行的釋放monitor 的指令。

synchronized方法底層原理

方法級的同步是隱式,即無需通過字節(jié)碼指令來控制的,它實現(xiàn)在方法調(diào)用和返回操作之中。JVM可以從方法常量池中的方法表結(jié)構(method_info Structure) 中的 ACC_SYNCHRONIZED 訪問標志區(qū)分一個方法是否同步方法。當方法調(diào)用時,調(diào)用指令將會 檢查方法的 ACC_SYNCHRONIZED 訪問標志是否被設置,如果設置了,執(zhí)行線程將先持有monitor(虛擬機規(guī)范中用的是管程一詞), 然后再執(zhí)行方法,最后再方法完成(無論是正常完成還是非正常完成)時釋放monitor。在方法執(zhí)行期間,執(zhí)行線程持有了monitor,其他任何線程都無法再獲得同一個monitor。如果一個同步方法執(zhí)行期間拋 出了異常,并且在方法內(nèi)部無法處理此異常,那這個同步方法所持有的monitor將在異常拋到同步方法之外時自動釋放。

我們看看字節(jié)碼層面如何實現(xiàn):

public class SyncMethod {public int i;public synchronized void syncTask(){i++;}
}

使用javap反編譯后的字節(jié)碼如下:

Classfile /Users/zejian/Downloads/Java8_Action/src/main/java/com/zejian/concurrencys/SyncMethod.classLast modified 2017-6-2; size 308 bytesMD5 checksum f34075a8c059ea65e4cc2fa610e0cd94Compiled from "SyncMethod.java"
public class com.zejian.concurrencys.SyncMethodminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool;//省略沒必要的字節(jié)碼//==================syncTask方法======================public synchronized void syncTask();descriptor: ()V//方法標識ACC_PUBLIC代表public修飾,ACC_SYNCHRONIZED指明該方法為同步方法flags: ACC_PUBLIC, ACC_SYNCHRONIZEDCode:stack=3, locals=1, args_size=10: aload_01: dup2: getfield      #2                  // Field i:I5: iconst_16: iadd7: putfield      #2                  // Field i:I10: returnLineNumberTable:line 12: 0line 13: 10
}
SourceFile: "SyncMethod.java"

從字節(jié)碼中可以看出,synchronized修飾的方法并沒有monitorenter指令和monitorexit指令,取得代之的確實是ACC_SYNCHRONIZED標識,該標識指明了該方法是一個同步方法,JVM通過該ACC_SYNCHRONIZED訪問標志來辨別一個方法是否聲明為同步方法,從而執(zhí)行相應的同步調(diào)用。操作系統(tǒng)實現(xiàn)線程之間的切換時需要從用戶態(tài)轉(zhuǎn)換到內(nèi)核態(tài)

Java虛擬機對synchronized的優(yōu)化

鎖的狀態(tài)總共有四種,無鎖狀態(tài)、偏向鎖、輕量級鎖和重量級鎖。隨著鎖的競爭,鎖可以從偏向鎖升級到輕量級鎖,再升級的重量級鎖,但是鎖的升級是單向的,也就是說只能從低到高升級,不會出現(xiàn)鎖的降級

偏向鎖 在大多數(shù)情況下,鎖不僅不存在多線程競爭,而且總是由同一線程多次獲得,因此為了減少同一線程獲取鎖(會涉及到一些CAS操作,耗時)的代價而引入偏向鎖。偏向鎖的核心思想是,如果一個線程獲得了鎖,那么鎖就進入偏向模式,此時Mark Word 的結(jié)構也變?yōu)槠蜴i結(jié)構,當這個線程再次請求鎖時,無需再做任何同步操作,即獲取鎖的過程,這樣就省去了大量有關鎖申請的操作,從而也就提供程序的性能。

但是對于鎖競爭比較激烈的場合,偏向鎖就失效了,偏向鎖失敗后,并不會立即膨脹為重量級鎖,而是先升級為輕量級鎖。

輕量級鎖 量級鎖能夠提升程序性能的依據(jù)是“對絕大部分的鎖,在整個同步周期內(nèi)都不存在競爭”,注意這是經(jīng)驗數(shù)據(jù)。需要了解的是,輕量級鎖所適應的場景是線程交替執(zhí)行同步塊的場合,如果存在同一時間訪問同一鎖的場合,就會導致輕量級鎖膨脹為重量級鎖。

自旋鎖 虛擬機為了避免線程真實地在操作系統(tǒng)層面掛起,還會進行一項稱為自旋鎖的優(yōu)化手段。這是基于在大多數(shù)情況下,線程持有鎖的時間都不會太長,如果直接掛起操作系統(tǒng)層面的線程可能會得不償失,畢竟操作系統(tǒng)實現(xiàn)線程之間的切換時需要從用戶態(tài)轉(zhuǎn)換到核心態(tài),這個狀態(tài)之間的轉(zhuǎn)換需要相對比較長的時間,時間成本相對較高,因此自旋鎖會假設在不久將來,當前的線程可以獲得鎖,因此虛擬機會讓當前想要獲取鎖的線程做幾個空循環(huán)(這也是稱為自旋的原因),一般不會太久,可能是50個循環(huán)或100循環(huán),在經(jīng)過若干次循環(huán)后,如果得到鎖,就順利進入臨界區(qū)。如果還不能獲得鎖,那就會將線程在操作系統(tǒng)層面掛起,這就是自旋鎖的優(yōu)化方式,這種方式確實也是可以提升效率的。最后沒辦法也就只能升級為重量級鎖了。

鎖消除 Java虛擬機在JIT編譯時(可以簡單理解為當某段代碼即將第一次被執(zhí)行時進行編譯,又稱即時編譯),通過對運行上下文的掃描,去除不可能存在共享資源競爭的鎖,通過這種方式消除沒有必要的鎖,可以節(jié)省毫無意義的請求鎖時間,如下StringBuffer的append是一個同步方法,但是在add方法中的StringBuffer屬于一個局部變量,并且不會被其他線程所使用,因此StringBuffer不可能存在共享資源競爭的情景,JVM會自動將其鎖消除。

關于synchronized 可能需要了解的關鍵點

一個線程調(diào)用synchronized方法的同時在其方法體內(nèi)部調(diào)用該對象另一個synchronized方法,也就是說一個線程得到一個對象鎖后再次請求該對象鎖,是允許的,這就是synchronized的可重入性。如下:

public class AccountingSync implements Runnable{static AccountingSync instance=new AccountingSync();static int i=0;static int j=0;@Overridepublic void run() {for(int j=0;j<1000000;j++){//this,當前實例對象鎖synchronized(this){i++;increase();//synchronized的可重入性}}}public synchronized void increase(){j++;}public static void main(String[] args) throws InterruptedException {Thread t1=new Thread(instance);Thread t2=new Thread(instance);t1.start();t2.start();t1.join();t2.join();System.out.println(i);}
}

在獲取當前實例對象鎖后進入synchronized代碼塊執(zhí)行同步代碼,并在代碼塊中調(diào)用了當前實例對象的另外一個synchronized方法,再次請求當前實例鎖時,將被允許,進而執(zhí)行方法體代碼,這就是重入鎖最直接的體現(xiàn),需要特別注意另外一種情況,當子類繼承父類時,子類也是可以通過可重入鎖調(diào)用父類的同步方法。注意由于synchronized是基于monitor實現(xiàn)的,因此每次重入,monitor中的計數(shù)器仍會加1。

線程中斷與synchronized

正如中斷二字所表達的意義,在線程運行(run方法)中間打斷它,在Java中,提供了以下3個有關線程中斷的方法

//中斷線程(實例方法)
public void Thread.interrupt();//判斷線程是否被中斷(實例方法)
public boolean Thread.isInterrupted();//判斷是否被中斷并清除當前中斷狀態(tài)(靜態(tài)方法)
public static boolean Thread.interrupted();

當一個線程處于被阻塞狀態(tài)或者試圖執(zhí)行一個阻塞操作時,使用Thread.interrupt()方式中斷該線程,注意此時將會拋出一個InterruptedException的異常,同時中斷狀態(tài)將會被復位(由中斷狀態(tài)改為非中斷狀態(tài)),如下代碼將演示該過程:

public class InterruputSleepThread3 {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread() {@Overridepublic void run() {//while在try中,通過異常中斷就可以退出run循環(huán)try {while (true) {//當前線程處于阻塞狀態(tài),異常必須捕捉處理,無法往外拋出TimeUnit.SECONDS.sleep(2);}} catch (InterruptedException e) {System.out.println("Interruted When Sleep");boolean interrupt = this.isInterrupted();//中斷狀態(tài)被復位System.out.println("interrupt:"+interrupt);}}};t1.start();TimeUnit.SECONDS.sleep(2);//中斷處于阻塞狀態(tài)的線程t1.interrupt();/*** 輸出結(jié)果:Interruted When Sleepinterrupt:false*/}
}

除了阻塞中斷的情景,我們還可能會遇到處于運行期且非阻塞的狀態(tài)的線程,這種情況下,直接調(diào)用Thread.interrupt()中斷線程是不會得到任響應的,如下代碼,將無法中斷非阻塞狀態(tài)下的線程:

public class InterruputThread {public static void main(String[] args) throws InterruptedException {Thread t1=new Thread(){@Overridepublic void run(){while(true){System.out.println("未被中斷");}}};t1.start();TimeUnit.SECONDS.sleep(2);t1.interrupt();/*** 輸出結(jié)果(無限執(zhí)行):未被中斷未被中斷未被中斷......*/}
}

雖然我們調(diào)用了interrupt方法,但線程t1并未被中斷,因為處于非阻塞狀態(tài)的線程需要我們手動進行中斷檢測并結(jié)束程序,改進后代碼如下:

public class InterruputThread {public static void main(String[] args) throws InterruptedException {Thread t1=new Thread(){@Overridepublic void run(){while(true){//判斷當前線程是否被中斷if (this.isInterrupted()){System.out.println("線程中斷");break;}}System.out.println("已跳出循環(huán),線程中斷!");}};t1.start();TimeUnit.SECONDS.sleep(2);t1.interrupt();/*** 輸出結(jié)果:線程中斷已跳出循環(huán),線程中斷!*/}
}

簡單總結(jié)一下中斷兩種情況,一種是當線程處于阻塞狀態(tài)或者試圖執(zhí)行一個阻塞操作時,我們可以使用實例方法interrupt()進行線程中斷,執(zhí)行中斷操作后將會拋出interruptException異常(該異常必須捕捉無法向外拋出)并將中斷狀態(tài)復位,另外一種是當線程處于運行狀態(tài)時,我們也可調(diào)用實例方法interrupt()進行線程中斷,但同時必須手動判斷中斷狀態(tài),并編寫中斷線程的代碼(其實就是結(jié)束run方法體的代碼)。有時我們在編碼時可能需要兼顧以上兩種情況,那么就可以如下編寫:

public void run(){try {//判斷當前線程是否已中斷,注意interrupted方法是靜態(tài)的,執(zhí)行后會對中斷狀態(tài)進行復位while (!Thread.interrupted()) {TimeUnit.SECONDS.sleep(2);}} catch (InterruptedException e) {}
}

中斷與synchronized

線程的中斷操作對于正在等待獲取的鎖對象的synchronized方法或者代碼塊并不起作用,也就是對于synchronized來說,如果一個線程在等待鎖,那么結(jié)果只有兩種,要么它獲得這把鎖繼續(xù)執(zhí)行,要么它就保存等待,即使調(diào)用中斷線程的方法,也不會生效。

/*** Created by zejian on 2017/6/2.* Blog : http://blog.csdn.net/javazejian [原文地址,請尊重原創(chuàng)]*/
public class SynchronizedBlocked implements Runnable{public synchronized void f() {System.out.println("Trying to call f()");while(true) // Never releases lockThread.yield();}/*** 在構造器中創(chuàng)建新線程并啟動獲取對象鎖*/public SynchronizedBlocked() {//該線程已持有當前實例鎖new Thread() {public void run() {f(); // Lock acquired by this thread}}.start();}public void run() {//中斷判斷while (true) {if (Thread.interrupted()) {System.out.println("中斷線程!!");break;} else {f();}}}public static void main(String[] args) throws InterruptedException {SynchronizedBlocked sync = new SynchronizedBlocked();Thread t = new Thread(sync);//啟動后調(diào)用f()方法,無法獲取當前實例鎖處于等待狀態(tài)t.start();TimeUnit.SECONDS.sleep(1);//中斷線程,無法生效t.interrupt();}
}

我們在SynchronizedBlocked構造函數(shù)中創(chuàng)建一個新線程并啟動獲取調(diào)用f()獲取到當前實例鎖,由于SynchronizedBlocked自身也是線程,啟動后在其run方法中也調(diào)用了f(),但由于對象鎖被其他線程占用,導致t線程只能等到鎖,此時我們調(diào)用了t.interrupt();但并不能中斷線程。

等待喚醒機制與synchronized

notify/notifyAll和wait方法,在使用這3個方法時,必須處于synchronized代碼塊或者synchronized方法中,否則就會拋出IllegalMonitorStateException異常,這是因為調(diào)用這幾個方法前必須拿到當前對象的監(jiān)視器monitor對象

synchronized (obj) {obj.wait();obj.notify();obj.notifyAll();         }

與sleep方法不同的是wait方法調(diào)用完成后,線程將被暫停,**但wait方法將會釋放當前持有的監(jiān)視器鎖(monitor),直到有線程調(diào)用notify/notifyAll方法后方能繼續(xù)執(zhí)行,而sleep方法只讓線程休眠并不釋放鎖。**同時notify/notifyAll方法調(diào)用后,并不會馬上釋放監(jiān)視器鎖,而是在相應的synchronized(){}/synchronized方法執(zhí)行結(jié)束后才自動釋放鎖。

更多Android相關文章:

Android如何進階:http://docs.qq.com/doc/DWHFqVHBMVEJPWUx
Android面試題匯總:http://docs.qq.com/doc/DWGZIRFh5VEtYWE1D
Android音視頻需要學習哪些:http://docs.qq.com/doc/DWFFWZHNPTHZVdHFX
Android常有的開源框架有哪些框:docs.qq.com/doc/DWHlGYUdseVhsSUda
Android車載應需要學習哪些:docs.qq.com/doc/DWEl0blBabXVvU2Nw Android
Framework怎么學:docs.qq.com/doc/DWFdlc2JocEtNbEJ1

http://www.risenshineclean.com/news/8119.html

相關文章:

  • 公司網(wǎng)站開發(fā)費用濟南興田德潤o簡介圖片seo技術培訓東莞
  • 用織夢的網(wǎng)站怎么做推廣廣州最新疫情最新消息
  • 網(wǎng)頁界面設計的構成要素電商seo是什么意思啊
  • 速拓科技是做網(wǎng)站sem網(wǎng)絡營銷
  • 本地網(wǎng)站建設百度的人工客服電話
  • 網(wǎng)站做跳轉(zhuǎn)對排名有影響嗎百度識別圖片找圖
  • 有哪些網(wǎng)站做汽車周邊服務360手機優(yōu)化大師下載
  • 做網(wǎng)站的銷售團隊合肥網(wǎng)絡推廣服務
  • 海星wap建站培訓計劃方案
  • 做網(wǎng)站都要學什么互換鏈接的方法
  • 知乎 網(wǎng)站開發(fā)工具百度關鍵詞價格排行榜
  • wordpress自定義二級菜單的標簽網(wǎng)絡優(yōu)化app
  • 中國最頂尖的平面設計公司網(wǎng)站優(yōu)化最為重要的內(nèi)容是
  • 濟南做網(wǎng)站注冊一個域名需要多少錢
  • wordpress外國人留言長春seo按天計費
  • wordpress跳轉(zhuǎn)到登錄頁面代碼aso優(yōu)化貼吧
  • 深圳網(wǎng)站公司制作重慶seo搜索引擎優(yōu)化優(yōu)與略
  • 昆明小程序開發(fā)公司黑帽seo什么意思
  • 網(wǎng)站建設山東聚搜網(wǎng)絡一x系統(tǒng)優(yōu)化app最新版
  • 網(wǎng)站線上體系如何網(wǎng)絡媒體推廣
  • 企業(yè)網(wǎng)站建設合同百度網(wǎng)站優(yōu)化方案
  • 網(wǎng)站開發(fā)后如何上線濟南seo公司報價
  • 濮陽市網(wǎng)站建設寧波網(wǎng)絡營銷怎么做
  • 頁面設計公司排名seo有哪些優(yōu)化工具
  • 程序開發(fā)步驟深圳seo公司排名
  • 三方物流網(wǎng)站建設網(wǎng)站老域名跳轉(zhuǎn)到新域名
  • 做網(wǎng)站用html還是phpseo網(wǎng)站平臺
  • 騰訊微信網(wǎng)站建設價格seo軟件資源
  • 用什么軟件做動漫視頻網(wǎng)站seo引擎優(yōu)化公司
  • 用織夢做的網(wǎng)站怎樣看品牌運營包括哪些內(nèi)容