Java并發(fā)編程中的synchronized解析
一:synchronized的作用范圍
synchronized可作用在普通的方法上,靜態(tài)方法上以及同步代碼塊上。以下,我將分別的對(duì)這三種情況做一個(gè)分析。
1:作用于普通方法上
public class Demo01 implements Runnable{
private int a;
private synchronized void add() {
a++;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
add();
}
}
public static void main(String[] args) {
Demo01 demo01 =new Demo01();
Thread thread1 =new Thread(demo01);
Thread thread2 =new Thread(demo01);
thread1.start();
thread2.start();
}
}
兩個(gè)線(xiàn)程對(duì)變量a各進(jìn)行100次的自加,在add方法上加了synchronized以達(dá)到線(xiàn)程間的同步效果。synchronized加在方法上,持有鎖的為該類(lèi)的實(shí)例對(duì)象,即本例的demo01。所以?xún)蓚€(gè)線(xiàn)程訪(fǎng)問(wèn)同一個(gè)鎖對(duì)象會(huì)有互斥情況。 如果這里每個(gè)線(xiàn)程持有的為兩個(gè)不同的類(lèi)實(shí)例,如下:
Demo01 demo01 =new Demo01();
Demo01 demo02 =new Demo01();
Thread thread1 =new Thread(demo01); //demo01
Thread thread2 =new Thread(demo02); //demo02
很明顯,這里在方法上加上synchronized來(lái)同步是不行的,因?yàn)檫@里是兩個(gè)new出來(lái)的不同的實(shí)例,如果想要通過(guò)的該類(lèi)的不同實(shí)例來(lái)加鎖,我們可以通過(guò)下面的方式’。
2:作用于靜態(tài)方法上
我們知道靜態(tài)方法是歸屬于類(lèi)所有的,同一個(gè)類(lèi)的不同實(shí)例可以通過(guò)持有其類(lèi)的相同Class來(lái)達(dá)到線(xiàn)程同步的效果。
如下:
public class Demo02 implements Runnable{
private static int a;
private synchronized static void add() {
a++;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
add();
}
}
public static void main(String[] args) {
Demo02 demo01 =new Demo02();
Demo02 demo02 =new Demo02();
Thread thread1 =new Thread(demo01);
Thread thread2 =new Thread(demo02);
thread1.start();
thread2.start();
}
}
創(chuàng)建線(xiàn)程使用的為同一個(gè)類(lèi)的不同實(shí)例,調(diào)用靜態(tài)方法的時(shí)候,還是能夠達(dá)到線(xiàn)程同步的效果。因?yàn)榇藭r(shí)持有鎖對(duì)象的為類(lèi)的Class字節(jié)碼。 除了上面兩種方式,還可以通過(guò)同步代碼塊的方式來(lái)進(jìn)行加鎖操作。
3:作用于同步代碼塊上
public class Demo03 implements Runnable{
private int a;
private void add() {
synchronized (Object.class){
a++;
}
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
add();
}
}
public static void main(String[] args) {
Demo03 demo01 =new Demo03();
Demo03 demo02 =new Demo03();
Thread thread1 =new Thread(demo01);
Thread thread2 =new Thread(demo02);
thread1.start();
thread2.start();
}
}
以上例子持有鎖對(duì)象的為Object的Class,這里應(yīng)該注意的是,在同步代碼塊中,只要能夠保證每個(gè)線(xiàn)程過(guò)來(lái)時(shí),是同一個(gè)對(duì)象即可(任何類(lèi)型的同一個(gè)實(shí)例對(duì)象)
二:synchronized同步的原理
synchronized的實(shí)現(xiàn)原理中,同步代碼塊與同步方法,同步靜態(tài)方法是不一樣的。在同步代碼塊中,是通過(guò)現(xiàn)實(shí)的監(jiān)視器對(duì)象來(lái)標(biāo)識(shí)的。而同步方法和同步靜態(tài)是通過(guò)同步方法來(lái)標(biāo)識(shí)的。通過(guò)查看其源碼的字節(jié)碼文件,我們可以清楚的看到其原理。
同步代碼塊字節(jié)碼文件:
public void add();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=1
0: aload_0
1: dup
2: astore_1
3: monitorenter //持有鎖
4: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #3 // String Aaa
9: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
12: aload_1
13: monitorexit //釋放鎖
14: goto 22
17: astore_2
18: aload_1
19: monitorexit //釋放鎖
20: aload_2
21: athrow
22: return
Exception table:
from to target type
4 14 17 any
17 20 17 any
LineNumberTable:
line 6: 0
line 7: 4
line 8: 12
line 9: 22
LocalVariableTable:
Start Length Slot Name Signature
0 23 0 this Lcom/sg/thread002/threadSynchronized/Demo04;
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 17
locals = [ class com/sg/thread002/threadSynchronized/Demo04, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
可以看到同步代碼塊是直接顯示的執(zhí)行monitorenter和monitorexit ,JVM保證無(wú)論在什么情況下,執(zhí)行完同步的代碼塊,就會(huì)釋放鎖,所以會(huì)有兩個(gè)monitorexit,另一個(gè)則是保證在異常的時(shí)候也是能夠釋放掉鎖的。
同步普通方法與靜態(tài)方法:
public static synchronized void add();
descriptor: ()V
//同步的標(biāo)識(shí)
//ACC_PUBLIC :公共方法
//ACC_STATIC :靜態(tài)方法
//ACC_SYNCHRONIZED :同步方法標(biāo)識(shí)
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=0, args_size=0
0: getstatic #2 // Field a:I
3: iconst_1
4: iadd
5: putstatic #2 // Field a:I
8: return
LineNumberTable:
line 7: 0
line 8: 8
這里可以看到在方法級(jí)別的同步是通過(guò)ACC_SYNCHRONIZED來(lái)標(biāo)識(shí)的。
到這里,關(guān)于synchronized就其使用的范圍以及原理做了一個(gè)分析,雖然說(shuō)其是一個(gè)重量級(jí)的鎖,但是JDK在1.6的時(shí)候?qū)ζ溥M(jìn)行了優(yōu)化,引入的偏向鎖,提高其性能。于此同時(shí),synchronized也是一種可重入的鎖。
到此這篇關(guān)于Java并發(fā)編程中的synchronized解析的文章就介紹到這了,更多相關(guān)Java的synchronized解析內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java?實(shí)現(xiàn)使用Comparable按照我們指定的規(guī)則排序
這篇文章主要介紹了Java?如何使用Comparable按照我們指定的規(guī)則排序,通過(guò)練習(xí)創(chuàng)建TreeSet集合使用無(wú)參構(gòu)造方法,并按照年齡從小到大的順序排序,若年齡相同再按照姓名的字母順序排序展開(kāi)內(nèi)容,需要的朋友可以參考一下2022-04-04
Java實(shí)現(xiàn)對(duì)視頻進(jìn)行截圖的方法【附ffmpeg下載】
這篇文章主要介紹了Java實(shí)現(xiàn)對(duì)視頻進(jìn)行截圖的方法,結(jié)合實(shí)例形式分析了Java使用ffmpeg針對(duì)視頻進(jìn)行截圖的相關(guān)操作技巧,并附帶ffmpeg.exe文件供讀者下載使用,需要的朋友可以參考下2018-01-01
SpringBoot+Mybatis+Vue 實(shí)現(xiàn)商品模塊的crud操作
這篇文章主要介紹了SpringBoot+Mybatis+Vue 實(shí)現(xiàn)商品模塊的crud操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Java實(shí)現(xiàn)中文算數(shù)驗(yàn)證碼的實(shí)現(xiàn)示例(算數(shù)運(yùn)算+-*/)
這篇文章主要介紹了Java實(shí)現(xiàn)中文算數(shù)驗(yàn)證碼的實(shí)現(xiàn)示例(算數(shù)運(yùn)算+-*/),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
java中public class與class的區(qū)別詳解
以下是對(duì)java中public class與class的區(qū)別進(jìn)行了分析介紹,需要的朋友可以過(guò)來(lái)參考下2013-07-07
Java使用hutool實(shí)現(xiàn)文件大小的友好輸出
這篇文章主要為大家詳細(xì)介紹了Java如何使用hutool實(shí)現(xiàn)文件大小的友好輸出,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解下2023-11-11
Java圖片與Base64互轉(zhuǎn)工具類(lèi)實(shí)現(xiàn)過(guò)程
本文介紹了Java中實(shí)現(xiàn)圖片與Base64編碼轉(zhuǎn)換的工具類(lèi),包括本地圖片轉(zhuǎn)Base64編碼、網(wǎng)絡(luò)圖片轉(zhuǎn)Base64編碼、Base64編碼轉(zhuǎn)圖片文件等功能,工具類(lèi)使用了Java標(biāo)準(zhǔn)庫(kù)和Apache Commons庫(kù),通過(guò)Java NIO實(shí)現(xiàn)高效的文件操作,感興趣的朋友跟隨小編一起看看吧2026-01-01
SpringRetry重試機(jī)制之@Retryable注解與重試策略詳解
本文將詳細(xì)介紹SpringRetry的重試機(jī)制,特別是@Retryable注解的使用及各種重試策略的配置,幫助開(kāi)發(fā)者構(gòu)建更加健壯的應(yīng)用程序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04
SpringBoot配置SwaggerUI訪(fǎng)問(wèn)404錯(cuò)誤的解決方法
這篇文章主要為大家詳細(xì)介紹了SpringBoot配置SwaggerUI訪(fǎng)問(wèn)404錯(cuò)誤的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12

