日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

java synchronized 原理_Java Synchronized的原理

發(fā)布時間:2024/9/19 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java synchronized 原理_Java Synchronized的原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

我們先通過反編譯下面的代碼來看看Synchronized是如何實現(xiàn)對代碼塊進行同步的:

public classSynchronizedDemo{public voidmethod(){synchronized(this){

System.out.println("Method 1 start");

}

}

}

反編譯

可以看到有monitorenter和monitorexit兩條指令

關(guān)于這兩條指令的描述我們參考JVM規(guī)范:

monitorenter:

Each object is associated with a monitor. A monitor is locked if and only if it has an owner. The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref, as follows:

? If the entry count of the monitor associated with objectref is zero, the thread enters the monitor and sets its entry count to one. The thread is then the owner of the monitor.

? If the thread already owns the monitor associated with objectref, it reenters the monitor, incrementing its entry count.

? If another thread already owns the monitor associated with objectref, the thread blocks until the monitor's entry count is zero, then tries again to gain ownership.

大概意思是說:

每個對象都有一個監(jiān)視器鎖(monitor)。當monitor被占用時就會處于鎖定狀態(tài),線程執(zhí)行monitorenter指令時嘗試獲取monitor的所有權(quán),過程如下:

1.如果monitor的進入數(shù)為0,則該線程進入monitor,然后將進入數(shù)設(shè)置為1,該線程即為monitor的所有者。

2.如果線程已經(jīng)占有該monitor,只是重新計入,則進入monitor的進入數(shù)加1.

2.如果其他線程已經(jīng)占用了monitor,則該線程進入阻塞狀態(tài),直到monitor的進入數(shù)為0,再重新嘗試獲取monitor的所有權(quán)。

monitorexit:

The thread that executes monitorexit must be the owner of the monitor associated with the instance referenced by objectref.

The thread decrements the entry count of the monitor associated with objectref. If as a result the value of the entry count is zero, the thread exits the monitor and is no longer its owner. Other threads that are blocking to enter the monitor are allowed to attempt to do so.

這段話的大概意思是說:

執(zhí)行monitorexit的線程必須是objectref說對應(yīng)的monitor的所有者。

執(zhí)行指令時,monitor的進入數(shù)減1.如果減1后進入數(shù)為0,那線程退出monitor,不再是這個monitor的所有者,奇特被這個monitor阻塞的線程可以嘗試去獲取這個monitor的所有權(quán)。

通過這兩段描述,我們應(yīng)該能很清楚的看出Synchronized的實現(xiàn)原理,Synchronized的語義底層是通過一個monitor的對象來完成,其實wait/notify等黨閥也是依賴于monitor對象,這就是為什么只有在同步的塊或者方法中才能調(diào)用wait/notify等方法,否則會拋出java.lang.IllegalMonitorStateException的異常的原因。

方法的同步?jīng)]有通過指令monitorenter和monitorexit來完成(理論上其實也可以通過這兩條指令來實現(xiàn)),不過相對于普通方法,其常量池中多了ACC_SYNCHRONIZED標識符。JVM就是根據(jù)該標識符來實現(xiàn)方法的同步:當方法調(diào)用時,調(diào)用指令將會檢查方法的ACC_SYNCHRONIZED訪問標志是否被設(shè)置,如果設(shè)置了,執(zhí)行線程將先獲取monitor,獲取成功后才能執(zhí)行該方法,方法執(zhí)行完后在釋放monitor。在方法執(zhí)行期間,其他任何線程都無法再獲得同一個monitor對象。其實本質(zhì)上沒有區(qū)別,只是方法的同步上是一種隱私的方式來實現(xiàn),無需通過字節(jié)碼來完成。

Synchronized的基本使用

Synchronized是java中解決并發(fā)問題的一種最常用的方法,也是最簡單的一種方法。Synchronized的作用主要有三個:

(1)確保線程互斥的訪問同步代碼

(2)保證共享變量的修改能夠急事課件

(3)有效解決重拍問題。

從語法上將,Synchronized總共有三種用法:

(1)修飾普通方法

(2)修飾靜態(tài)方法

(3)修飾代碼塊

接下來我就通過幾個立在程序來說明一下這三種方式:

1.沒有同步的情況:

public classSynchronizedTest {public voidmethod1(){

System.out.println("Method 1 start");try{

System.out.println("Method 1 execute");

Thread.sleep(3000);

}catch(InterruptedException e){

e.printStackTrace();

}

System.out.println("Method 1 end");

}public voidmethod2(){

System.out.println("Method 2 start");try{

System.out.println("Method 2 execute");

Thread.sleep(3000);

}catch(InterruptedException e){

e.printStackTrace();

}

System.out.println("Method 2 end");

}public static voidmain(String[] args) {//TODO Auto-generated method stub

final SynchronizedTest test = newSynchronizedTest();new Thread(newRunnable(){

@Overridepublic voidrun(){

test.method1();

}

}).start();new Thread(newRunnable(){

@Overridepublic voidrun(){

test.method2();

}

}).start();

}

}

執(zhí)行結(jié)果為

Method 1start

Method1execute

Method2start

Method2execute

Method2end

Method1 end

View Code

2.對普通方法同步

public classSynchronizedTest {public synchronized voidmethod1(){

System.out.println("Method 1 start");try{

System.out.println("Method 1 execute");

Thread.sleep(3000);

}catch(InterruptedException e){

e.printStackTrace();

}

System.out.println("Method 1 end");

}public synchronized voidmethod2(){

System.out.println("Method 2 start");try{

System.out.println("Method 2 execute");

Thread.sleep(3000);

}catch(InterruptedException e){

e.printStackTrace();

}

System.out.println("Method 2 end");

}public static voidmain(String[] args) {//TODO Auto-generated method stub

final SynchronizedTest test = newSynchronizedTest();new Thread(newRunnable(){

@Overridepublic voidrun(){

test.method1();

}

}).start();new Thread(newRunnable(){

@Overridepublic voidrun(){

test.method2();

}

}).start();

}

}

執(zhí)行結(jié)果為:

Method 1start

Method1execute

Method1end

Method2start

Method2execute

Method2 end

View Code

3.靜態(tài)方法(類)同步

public classSynchronizedTest {public static synchronized voidmethod1(){

System.out.println("Method 1 start");try{

System.out.println("Method 1 execute");

Thread.sleep(3000);

}catch(InterruptedException e){

e.printStackTrace();

}

System.out.println("Method 1 end");

}public static synchronized voidmethod2(){

System.out.println("Method 2 start");try{

System.out.println("Method 2 execute");

Thread.sleep(3000);

}catch(InterruptedException e){

e.printStackTrace();

}

System.out.println("Method 2 end");

}public static voidmain(String[] args) {//TODO Auto-generated method stub

final SynchronizedTest test = newSynchronizedTest();final SynchronizedTest test2 = newSynchronizedTest();new Thread(newRunnable(){

@Overridepublic voidrun(){

test.method1();

}

}).start();new Thread(newRunnable(){

@Overridepublic voidrun(){

test2.method2();

}

}).start();

}

}

執(zhí)行結(jié)果如下,對靜態(tài)方法的同步本質(zhì)上是對類的同步(靜態(tài)方法本質(zhì)上是屬于類的方法,而不是對象上的方法),所以即使test和test2屬于不同的對象,但是它們都屬于SynchronizedTest類的實例,所以也只能順序的執(zhí)行method1和method2,不能并發(fā)執(zhí)行。

Method 1start

Method1execute

Method1end

Method2start

Method2execute

Method2 end

View Code

4、代碼塊同步

public classSynchronizedTest {public voidmethod1(){

System.out.println("Method 1 start");try{synchronized (this) {

System.out.println("Method 1 execute");

Thread.sleep(3000);

}

}catch(InterruptedException e){

e.printStackTrace();

}

System.out.println("Method 1 end");

}public voidmethod2(){

System.out.println("Method 2 start");try{synchronized (this) {

System.out.println("Method 2 execute");

Thread.sleep(3000);

}

}catch(InterruptedException e){

e.printStackTrace();

}

System.out.println("Method 2 end");

}public static voidmain(String[] args) {//TODO Auto-generated method stub

final SynchronizedTest test = newSynchronizedTest();new Thread(newRunnable(){

@Overridepublic voidrun(){

test.method1();

}

}).start();new Thread(newRunnable(){

@Overridepublic voidrun(){

test.method2();

}

}).start();

}

}

執(zhí)行結(jié)果如下,雖然線程1和線程2都進入了對應(yīng)的方法開始執(zhí)行,但是線程2在進入同步塊之前,需要等待線程1中同步塊執(zhí)行完成。

Method 1start

Method1execute

Method2start

Method1end

Method2execute

Method2 end

View Code

總結(jié)

以上是生活随笔為你收集整理的java synchronized 原理_Java Synchronized的原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。