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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

synchronized不能锁静态变量_面试官:请说一下对象锁和类锁的区别

發(fā)布時(shí)間:2024/7/23 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 synchronized不能锁静态变量_面试官:请说一下对象锁和类锁的区别 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

有鎖才有自由

生活中不存在絕對(duì)的自由,絕對(duì)的自由通常對(duì)應(yīng)的無(wú)序和混沌,只有在道德、法律、倫理的約束下的相對(duì)自由,才能使人感受到自由。

而在多線程編程中,鎖是至關(guān)重要的,鎖就是道德,就是法律約束,沒(méi)有鎖的多線程環(huán)境將會(huì)是混亂的,所有線程都在爭(zhēng)奪資源,最后的結(jié)果就是導(dǎo)致系統(tǒng)崩潰,而有了鎖之后,多線程環(huán)境才能穩(wěn)定高效的工作。

synchronized 關(guān)鍵字

synchronized 是我們所說(shuō)的重量級(jí)鎖,所說(shuō)的重量級(jí)是相對(duì)于那些自旋鎖(AQS)而言的,比如可重入鎖ReentrantLock。很多人談 synchronized 色變,說(shuō)它性能差、太重,貌似言之鑿鑿。放在多年前確實(shí)如此,但是 Java 1.7、1.8 已經(jīng)對(duì) synchronized 做了很大優(yōu)化,其性能和那些輕量級(jí)鎖幾乎沒(méi)有差距。

所以,我們?cè)俪绦蛑衅鋵?shí)可以放心的使用它,即使沒(méi)有用過(guò),也肯定在一些源碼里見(jiàn)過(guò),比如 Netty 中就有很多地方用到了它。

下面開(kāi)始進(jìn)入今天的主題,類鎖和實(shí)例鎖??疵志鸵呀?jīng)很明顯了,類鎖就是所在類上的鎖,實(shí)例就是鎖在類實(shí)例上的鎖。

實(shí)例鎖

類聲明后,我們可以 new 出來(lái)很多的實(shí)例對(duì)象。這時(shí)候,每個(gè)實(shí)例在 JVM 中都有自己的引用地址和堆內(nèi)存空間,這時(shí)候,我們就認(rèn)為這些實(shí)例都是獨(dú)立的個(gè)體,很顯然,在實(shí)例上加的鎖和其他的實(shí)例就沒(méi)有關(guān)系,互不影響了。

通常我們使用實(shí)例鎖的方式有下面三種:

1、 鎖住實(shí)體里的非靜態(tài)變量

非靜態(tài)變量是實(shí)例自身變量,不會(huì)與其他實(shí)例共享,所以鎖住實(shí)體內(nèi)聲明的非靜態(tài)變量可以實(shí)現(xiàn)對(duì)象鎖。鎖住同一個(gè)變量的方法塊共享同一把鎖。

2、鎖住 this 對(duì)象

this 指的是當(dāng)前對(duì)象實(shí)例本身,所以,所有使用 synchronized(this)方式的方法都共享同一把鎖。

3、直接鎖非靜態(tài)方法

最簡(jiǎn)單、最直觀的一種方式,直接加在方法返回類型前。

使用對(duì)象鎖的情況,只有使用同一實(shí)例的線程才會(huì)受鎖的影響,多個(gè)實(shí)例調(diào)用同一方法也不會(huì)受影響。

下面來(lái)做個(gè)測(cè)試,開(kāi)啟 5 個(gè)線程,每個(gè)線程都 new 一個(gè)新的實(shí)例來(lái)分別調(diào)用上面三種方式的方法,方法完成的動(dòng)作就是輸出線程名稱,然后休眠 10 秒鐘。

public class ObjectLock { ?private Object lock = new Object(); ?/*** 鎖住非靜態(tài)變量* @throws InterruptedException*/public void lockObjectField() throws InterruptedException{synchronized (lock){System.out.println(Thread.currentThread().getName());Thread.sleep(10*1000);}} ?/*** 鎖住 this 對(duì)象 this 就是當(dāng)前對(duì)象實(shí)例* @throws InterruptedException*/public void lockThis() throws InterruptedException{synchronized (this){System.out.println(Thread.currentThread().getName());Thread.sleep(10*1000);}} ?/*** 直接鎖住非靜態(tài)方法* @throws InterruptedException*/public synchronized void methodLock() throws InterruptedException{System.out.println(Thread.currentThread().getName());Thread.sleep(10*1000);} ?public static void main(String[] args){for (int i = 0; i < 5; i++) {Thread worker = new Thread(new ObjectLockWorker());worker.setName("kite-" + i);worker.start();}} ?public static class ObjectLockWorker implements Runnable{@Overridepublic void run() {try {ObjectLock objectLock = new ObjectLock();// 方式 1objectLock.lockObjectField();// 方式 2//objectLock.lockThis();// 方式 3//objectLock.methodLock();} catch (Exception e) {e.printStackTrace();}}} }

我們預(yù)測(cè)的結(jié)果就是每個(gè)線程都會(huì)立刻輸出線程名稱,然后各自休眠 10 秒

分別調(diào)用方式1、2、3,效果都是一樣的,我們看到輸出結(jié)果和我們預(yù)測(cè)的是一樣的,5 個(gè)線程都立即輸出線程名,然后等待 10 秒,整個(gè)程序退出。

類鎖

類鎖是加載類上的,而類信息是存在 JVM 方法區(qū)的,并且整個(gè) JVM 只有一份,方法區(qū)又是所有線程共享的,所以類鎖是所有線程共享的。

使用類鎖的方式有如下方式:

1、鎖住類中的靜態(tài)變量

因?yàn)殪o態(tài)變量和類信息一樣也是存在方法區(qū)的并且整個(gè) JVM 只有一份,所以加在靜態(tài)變量上可以達(dá)到類鎖的目的。

2、直接在靜態(tài)方法上加 synchronized

因?yàn)殪o態(tài)方法同樣也是存在方法區(qū)的并且整個(gè) JVM 只有一份,所以加在靜態(tài)方法上可以達(dá)到類鎖的目的。

3、鎖住 xxx.class

對(duì)當(dāng)前類的 .class 屬性加鎖,可以實(shí)現(xiàn)類鎖。

類鎖是所有線程共享的鎖,所以同一時(shí)刻,只能有一個(gè)線程使用加了鎖的方法或方法體,不管是不是同一個(gè)實(shí)例。

下面同樣來(lái)做個(gè)測(cè)試,開(kāi)啟 5 個(gè)線程,除了調(diào)用靜態(tài)方法的方式,其他兩種方式中每個(gè)線程都 new 一個(gè)新的實(shí)例來(lái)分別調(diào)用,方法內(nèi)完成的動(dòng)作就是輸出線程名稱,然后休眠 10 秒鐘。

public class ClassLock { ?private static Object lock = new Object(); ?/*** 鎖住靜態(tài)變量* @throws InterruptedException*/public void lockStaticObjectField() throws InterruptedException{synchronized (lock){System.out.println(Thread.currentThread().getName());Thread.sleep(10*1000);}} ?/*** 鎖住靜態(tài)方法* @throws InterruptedException*/public static synchronized void methodLock() throws InterruptedException{System.out.println(Thread.currentThread().getName());Thread.sleep(10*1000);} ?/*** 鎖住 xxx.class* @throws InterruptedException*/public void lockClass() throws InterruptedException{synchronized (ClassLock.class){System.out.println(Thread.currentThread().getName());Thread.sleep(10*1000);}} ?public static void main(String[] args){for (int i = 0; i < 5; i++) {Thread worker = new Thread(new ClassLockWorker());worker.setName("kite-" + i);worker.start();}} ?public static class ClassLockWorker implements Runnable{@Overridepublic void run() {try {ClassLock classLock = new ClassLock();// 方式 1classLock.lockStaticObjectField();// 方式 2//ClassLock.methodLock();// 方式 3//classLock.lockClass();} catch (Exception e) {e.printStackTrace();}}} }

我們預(yù)測(cè)的結(jié)果就是剛開(kāi)始只有1個(gè)線程搶到鎖,然后輸出線程名,之后等待 10 秒中,之后是下一個(gè)搶到鎖的線程,輸出線程名,然后等待 10 秒。直到最后一個(gè)搶到鎖的線程,整個(gè)過(guò)程歷時(shí)大約 50 秒。

分別調(diào)用方式1、2、3,觀察執(zhí)行結(jié)果,和我們預(yù)測(cè)的是一致的。

怎么樣,面試再考你對(duì)象鎖和類鎖的時(shí)候,是不是能從容一點(diǎn)兒了呢。

你還可以讀:

Java 中的幾種線程池不知道你用對(duì)了沒(méi)有?mp.weixin.qq.com從 volatile 說(shuō)起,可見(jiàn)性和有序性是什么?mp.weixin.qq.com我們說(shuō)的 CAS 自旋鎖是什么?mp.weixin.qq.com

總結(jié)

以上是生活随笔為你收集整理的synchronized不能锁静态变量_面试官:请说一下对象锁和类锁的区别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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