1. 程式人生 > 實用技巧 >synchronized鎖物件之例項講解

synchronized鎖物件之例項講解

上次有個同學問個鎖的問題,只要清楚的瞭解兩個知識點就能解決,

知識點:

synchronized鎖方法相當於鎖物件;

sleep是Thread類的方法,不釋放鎖;

問題直接貼出來:

public class Test028_Sync implements Runnable{

    int b = 100;

    synchronized void m1() throws InterruptedException {
        b = 1000;
        Thread.sleep(500); //6
        System.out.println("b=" + b);
    }

    
synchronized void m2() throws InterruptedException { Thread.sleep(250); //5 b = 2000; } public static void main(String[] args) throws InterruptedException { Test028_Sync ts = new Test028_Sync(); Thread t = new Thread(ts); //1 t.start(); //2 ts.m2(); //3 System.out.println("main thread b=" + ts.b); //
4 } @Override public void run() { try { m1(); } catch (InterruptedException e) { e.printStackTrace(); } } }

輸出結果為?

分析:

1.main方法啟動首先去new一個ts例項,然後執行步驟1,步驟2使得t執行緒處於就緒狀態,等待jvm排程;

2.由於步驟2(t執行緒)與步驟3(main執行緒)都需要對ts物件持有鎖才能執行最終的m1(或m2)方法,所以這裡分兩個情況;

3.第一種情況:t執行緒獲得鎖,那麼先執行m1,列印"b=1000";緊接著main執行緒獲得鎖,執行m2,將賦值為2000,然後執行步驟4列印"main thread b=2000";最終結果為"b=1000 , main thread b=2000";

4.第二種情況:main執行緒先獲得鎖,那麼先執行m2,將b賦值為2000,然後釋放鎖,釋放鎖的同時會產生兩步並行操作===>“t執行緒獲得鎖” 和 “main執行緒繼續執行步驟4”,就得看那個操作先執行;

5.“t執行緒獲得鎖”--如果先執行,那麼先給b賦值為1000,接著列印b=1000,然後“main執行緒繼續執行步驟4”,因為此時b已被t執行緒賦值為1000,所以t執行緒列印 main thread b=1000;最終結果為"b=1000 , main thread b=2000";

6.“main執行緒繼續執行步驟4”--如果先執行,那麼列印main thread b=2000,然後“t執行緒獲得鎖”,列印b=1000;最終結果為"main thread b=2000, b=1000";

7.綜上所述,最終結果b一定列印1000,而main thread b有可能列印1000,有可能列印2000;

8.其實上面兩個方法中sleep沒啥作用;