日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

java多線程,靜態方法加鎖后,調用該方法會影響其它方法嗎?

從一個問題說起

一直想要把一些學習歷程和感悟記錄下來,卻沒有靜下心來好好思考一下,今天,就從同學問到的一個問題開始,對同一個類的靜態方法加鎖后,調用該方法,其他方法的調用會受到影響嗎?

對象鎖與類鎖

JAVA中每一個對象都持有一把鎖–monitor,monitor在操作系統中被稱為管程,也可翻譯為監視器,java中的monitor其實是對操作系統中monitor的一種實現(類似于接口與實現)。

對象鎖和類鎖本質其實是一樣的,只不過對象鎖指的是實例對象(所持有的monitor),而類鎖指的是類的Class對象。

synchronized

java中提供synchronized關鍵字與Object等來實現monitor機制的粒度控制。

synchronized修飾靜態方法,此刻的鎖指的是實例對象;

public synchronized static void syncStaticMethod(){

System.out.println("我是靜態方法,我被synchronized修飾。");

}

synchronized修飾非靜態方法,此刻的鎖指的是類的Class對象;

public synchronized void syncMethod(){

System.out.println("我是非靜態方法,我被synchronized修飾。");

}

synchronized修飾代碼塊,此刻的鎖指的是你所賦予synchronized的對象,與方法是否靜態無關;

public static void syncStaticBlockMethod() {

synchronized (Object.class) {

System.out.println("我是靜態方法,我被synchronized代碼塊修飾,此時的鎖對象是Object的Class對象。");

}

}

public void syncBlockMethod(){

synchronized (Object.class){

System.out.println("我是非靜態方法,我被synchronized代碼塊修飾,此時的鎖對象是Object的Class對象。");

}

}

分析

那么,對一個類的靜態方法加鎖,意味著什么?

其實,從上面我們已經可以得到答案了:當這個類的靜態方法被調用時,它會去獲取類鎖,準確的說是該類的Class對象的monitor,那么,其他方法會受到影響嗎?在這里,不妨做一個假設,那就是只要其他方法會競爭類的Class對象鎖,那么它便會陷入阻塞狀態(BLOCKED),直到獲取Class對象鎖,否則,便沒有影響。

當然,最初,我們還是應當使用代碼來證明(復制粘貼即可運行),如下:

/**

* @program: thinking-in-all

* @description:

* @author: Lucifinil

* @create: 2019-12-11

**/

public class SyncStaticYesAndNo implements Runnable {

public synchronized static void syncStaticYes1() {

try {

System.out.println(Thread.currentThread().getName() + " : 加鎖的靜態方法運行開始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 加鎖的靜態方法運行結束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public synchronized static void syncStaticYes2() {

try {

System.out.println(Thread.currentThread().getName() + " : 加鎖的靜態方法運行開始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 加鎖的靜態方法運行結束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public static void syncStaticNo() {

try {

System.out.println(Thread.currentThread().getName() + " : 不加鎖的靜態方法運行開始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 不加鎖的靜態方法運行結束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public synchronized void syncYes() {

try {

System.out.println(Thread.currentThread().getName() + " : 加鎖的非靜態方法運行開始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 加鎖的非靜態方法運行結束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public void syncNo() {

try {

System.out.println(Thread.currentThread().getName() + " : 不加鎖的非靜態方法運行開始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 不加鎖的非靜態方法運行結束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public static void syncStaticClassYes() {

synchronized (SyncStaticYesAndNo.class) {

try {

System.out.println(Thread.currentThread().getName() + " : 加Class對象鎖的靜態方法運行開始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 加Class對象鎖的靜態方法運行結束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

public void syncClassYes() {

synchronized (SyncStaticYesAndNo.class) {

try {

System.out.println(Thread.currentThread().getName() + " : 加Class對象鎖的非靜態方法運行開始n");

Thread.sleep(3000);

System.out.println(Thread.currentThread().getName() + " : 加Class對象鎖的非靜態方法運行結束");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

@Override

public void run() {

if (Thread.currentThread().getName().equals("Thread-0")) {

syncStaticYes1();

} else if (Thread.currentThread().getName().equals("Thread-1")) {

syncStaticYes2();

} else if (Thread.currentThread().getName().equals("Thread-2")) {

syncStaticNo();

} else if (Thread.currentThread().getName().equals("Thread-3")) {

syncYes();

} else if (Thread.currentThread().getName().equals("Thread-4")) {

syncNo();

} else if (Thread.currentThread().getName().equals("Thread-5")) {

syncStaticClassYes();

} else if (Thread.currentThread().getName().equals("Thread-6")) {

syncClassYes();

}

}

public static void main(String[] args) {

SyncStaticYesAndNo obj = new SyncStaticYesAndNo();

Thread t1 = new Thread(obj);

Thread t2 = new Thread(obj);

Thread t3 = new Thread(obj);

Thread t4 = new Thread(obj);

Thread t5 = new Thread(obj);

Thread t6= new Thread(obj);

Thread t7 = new Thread(obj);

t1.start();

t2.start();

t3.start();

t4.start();

t5.start();

t6.start();

t7.start();

}

}

這里,我們使用了七個線程來模擬多個情況,然后幾乎同時調用七個方法,由之前的分析,我們可以推測,只有競爭統一把鎖,才會產生阻塞情況,所以結果如下:

Thread-1 : 加鎖的靜態方法運行開始

Thread-3 : 加鎖的非靜態方法運行開始

Thread-2 : 不加鎖的靜態方法運行開始

Thread-4 : 不加鎖的非靜態方法運行開始

Thread-3 : 加鎖的非靜態方法運行結束

Thread-1 : 加鎖的靜態方法運行結束

Thread-2 : 不加鎖的靜態方法運行結束

Thread-6 : 加Class對象鎖的非靜態方法運行開始

Thread-4 : 不加鎖的非靜態方法運行結束

Thread-6 : 加Class對象鎖的非靜態方法運行結束

Thread-5 : 加Class對象鎖的靜態方法運行開始

Thread-5 : 加Class對象鎖的靜態方法運行結束

Thread-0 : 加鎖的靜態方法運行開始

Thread-0 : 加鎖的靜態方法運行結束

結論

我們可以看到,不加鎖的沒有受到任何影響,而加了鎖的非靜態方法也沒有受到任何影響,因為它所競爭的鎖并非是Class對象鎖,而是實例對象鎖,受到影響的有synchronized修飾的靜態方法,還有便是加了Class對象鎖的方法,本質上便是它們都在競爭當前類的Class對象鎖。

 
 
 
 

分享到:
標簽:多線程 java
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定