日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

对synchronized的一点理解

發(fā)布時間:2024/4/14 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 对synchronized的一点理解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、synchronized的使用
(一)、synchronized同步方法
1. “非線程安全”問題存在于“實例變量”中,如果是方法內部的私有變量,則不存在“非線程安全”問題。
2. 如果多個線程共同訪問1個對象中的實例變量,則有可能出現(xiàn)“非線程安全”問題。
3. synchronized取得的鎖都是對象鎖,而不是把一段代碼或方法當做鎖。因此在多線程訪問同一個對象時,哪個線程先執(zhí)行synchronized關鍵字的方法,哪個線程就持有該方法所屬對象的鎖lock,其他線程只能呈等待狀態(tài)。
但如果多個線程訪問多個對象,則JVM會創(chuàng)建多個鎖。
4. 調用關鍵字synchronized聲明的方法一定是排隊運行的。另外只有共享資源的讀寫訪問才需要同步化,如果不是共享資源,就沒有同步化的必要。
5. 臟讀。當A線程調用anyObject對象加入synchronized關鍵字的X方法時,A線程就獲得了X方法鎖,更準確地講,是獲得了對象的鎖,所以其他線程必須等A線程執(zhí)行完畢才可以調用X方法,但B線程可以隨意調用其他的非synchronized關鍵字的同步方法。
6. synchronized鎖重入。使用synchronized時,當一個線程得到一個對象鎖后,再次請求此對象鎖時,是可以再次得到該對象的鎖的。
7. 當一個線程執(zhí)行的代碼出現(xiàn)異常時,其所持有的鎖會自動釋放。
8. 同步不可以繼承。如果父類方法使用了關鍵字synchronized,那么子類方法不會繼承synchronized,如果子類需要同步,還需要在子類方法中添加synchronized。

(二)、synchronized同步代碼塊
1. 同一個方法中,不在synchronized塊中的就是異步執(zhí)行,在synchronized塊中的就是同步執(zhí)行。
2. 當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對同一個object中所有其他synchronized(this)同步代碼塊的訪問將被阻塞,這是因為synchronized使用的是“對象監(jiān)視器”。
3. 和synchronized方法一樣,synchronized(this)代碼塊也是鎖定當前對象。
4. java還支持對“任意對象”作為“對象監(jiān)視器”來實現(xiàn)同步的功能。這個任意對象大多數(shù)是實例變量及方法的參數(shù),使用格式為:synchronized(非this對象x),此時將x對象本身作為“對象監(jiān)視器”
鎖非this對象的優(yōu)點:如果在一個類中有很多個synchronized方法,這時雖然能實現(xiàn)同步,但會受到阻塞,所以影響運行效率;但如果使用同步代碼塊鎖非this對象,則synchronized(非this對象x)代碼塊中的程序與同步方法是異步的,不與其他鎖this同步方法爭搶this鎖,可以大大提高運行效率。
5. synchronized還可以應用在static靜態(tài)方法上,如果這樣寫,就是對當前的*.java文件對應的class類進行加鎖。
跟synchronized加到非static方法上的區(qū)別:synchronized加到static靜態(tài)方法上,是給Class類上鎖;而synchronized加到非static靜態(tài)方法上,是給對象上鎖。
6. 由于JVM具有String常量池緩存的功能,因此在大多數(shù)情況下,同步synchronized代碼塊都不使用String作為鎖對象:synchronized(string),而改用其他的,比如new Object實例化一個Object對象,但它并不放入緩存中。

以上方法的具體代碼例子可以參考《java多線程編程核心技術》

二、synchronized的實現(xiàn)原理

目前在Java中存在兩種鎖機制:synchronized和Lock
synchronized實現(xiàn)同步的基礎:Java中每一個對象都可以作為鎖,具體表現(xiàn)為以下3種方式:(Synchronized鎖, 鎖住的是對象。)
1. 對于普通同步方法,鎖是當前實例對象
2. 對于靜態(tài)同步方法,鎖是當前類的class對象
3. 對于同步方法塊,鎖是synchronized括號里配置的對象
synchronized用的鎖是存在java對象頭里的。重量級鎖、輕量級鎖和偏向鎖之間的轉換:

Synchronized同步塊和同步方法在實現(xiàn)上的區(qū)別:

在下面的例子中,使用了同步塊和同步方法,通過使用javap工具查看生成的class文件信息,來分析synchronized關鍵字的實現(xiàn)細節(jié)。

public class Synchronized {public static void main(String[] args) {// 對Synchronized Class對象進行加鎖synchronized (Synchronized.class) {}// 靜態(tài)同步方法,對Synchronized Class對象進行加鎖 m();}public static synchronized void m() {} }

在synchronized.class的同級目錄下執(zhí)行:javap -v synchronized.class,部分輸出如下:

說明:

public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATIC //方法修飾符,表示public staticCode:stack=2, locals=1, args_size=10: ldc #1 // class testnew/Synchronized2: dup 3: monitorenter // monitorenter:監(jiān)視器進入,獲取鎖4: monitorexit // monitorexit: 監(jiān)視器退出,釋放鎖5: invokestatic #16 // Method m:()V8: returnpublic static synchronized void m();descriptor: ()Vflags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED //方法修飾符,表示public static synchronizedCode: stack=0, locals=0, args_size=0 0: return

對于同步塊的實現(xiàn)使用了monitorenter和monitorexit指令,而同步方法則是依靠方法修飾符上的ACC_SYNCHRONIZED來完成的。無論采用哪種方法,其本質是對一個對象的監(jiān)視器(monitor)進行獲取,而這個獲取過程是排他的,也就是同一個時刻只能有一個線程獲取到由synchronized所保護對象的監(jiān)視器。

任意一個對象都擁有自己的監(jiān)視器,當這個對象由同步塊或者這個對象的同步方法調用時,執(zhí)行方法的線程必須先獲取到該對象的監(jiān)視器才能進入同步塊或者同步方法,而沒有獲取到監(jiān)視器(執(zhí)行該方法)的線程將會被阻塞在同步塊和同步方法的入口處,進入BLOCKED狀態(tài)。

下圖描述了對象、對象的監(jiān)視器、同步隊列和執(zhí)行線程之間的關系。

可以看出,任意線程對Object(Object由synchronized保護)的方法,首先要獲得Object的監(jiān)視器。如果獲取失敗,線程進入同步隊列,線程狀態(tài)變?yōu)锽LOCKED。當訪問Object的前驅(獲得了鎖的線程)釋放了鎖,則該釋放操作喚醒阻塞在同步隊列總的線程,使其重新嘗試對監(jiān)視器的獲取。

相關閱讀:java中的鎖分類?

參考:

《Java并發(fā)編程的藝術》

Java中的鎖機制 synchronized & 偏向鎖 & 輕量級鎖 & 重量級鎖 & 各自優(yōu)缺點及場景 & AtomicReference?

轉載于:https://www.cnblogs.com/zeroingToOne/p/8967445.html

總結

以上是生活随笔為你收集整理的对synchronized的一点理解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。