2017-06-05 41 views
0

我試過static函數和非靜態函數​​的訪問問題,一個函數是非同步的。如下面的代碼:多線程中的類鎖和對象鎖

public class Resource { 

public static synchronized void m1() throws InterruptedException { 
    System.out.println("Entering m1 method"); 
    Thread.sleep(10000); 
    System.out.println("Leaving m1 method"); 
    System.out.println(); 
} 

public synchronized void m2() throws InterruptedException { 
    System.out.println("Entering m2 method"); 
    Thread.sleep(2000); 
    System.out.println("Leaving m2 method"); 
    System.out.println(); 
} 

public void m3() throws InterruptedException { 
    System.out.println("Entering m3 method"); 
    Thread.sleep(2000); 
    System.out.println("Leaving m3 method"); 
    System.out.println(); 
} 

public synchronized void m4() throws InterruptedException { 
    System.out.println("Entering m4 method"); 
    Thread.sleep(2000); 
    System.out.println("Leaving m4 method"); 
    System.out.println(); 
} 

} 

public class ThreadDemo { 

public static void main(String[] args) { 

    final Resource resource = new Resource(); 

    Thread t1 = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      try { 
       resource.m1(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

     } 
    }); 

    Thread t2 = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      try { 
       resource.m2(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

     } 
    }); 

    Thread t3 = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      try { 
       resource.m3(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

     } 
    }); 

    Thread t4 = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      try { 
       resource.m4(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

     } 
    }); 

    t1.start(); 
    t2.start(); 
    t3.start(); 
    t4.start(); 
} 

} 

這裏創建了四個線程。

  1. T1被調用靜態同步(M1)
  2. T2,T4被調用同步(M2,M4)和
  3. T3是調用非synnchronized(立方米)。

它的輸出是:

Entering m1 method 
Entering m3 method 
Entering m2 method 
Leaving m3 method 

Leaving m2 method 

Entering m4 method 
Leaving m4 method 

Leaving m1 method 

我的問題是:

1)靜態同步方法使類級別的鎖。這裏什麼是類級鎖定的含義?如果一個線程已經被鎖定並且類級鎖被佔用,那麼爲什麼線程T2和T3開始執行?

2)T4正在等待完成T2。儘管同步應用於兩種不同的方法,那麼爲什麼T4還要等待呢?如果對象級別鎖定在T2,T4中工作,那麼爲什麼級別鎖定不起作用?

回答

2
  1. 靜態方法同步是

    public static void m1() { 
        synchronize (Resource.class) { 
        ... 
        } 
    } 
    
  2. 非靜態方法的同步等效爲

    public void m2() { 
        synchronize (this) { 
         ... 
        } 
    } 
    

等效現在,如果你看看這裏this正在用作顯示器,並且其中Resource.class對象正用作顯示器一切都應該變得清晰。

Java中的同步塊在某個對象上同步。同一對象上同步的所有同步塊只能同時在其中執行一個線程。所有其他嘗試進入同步塊的線程都會被阻塞,直到同步塊內的線程退出該塊。

在你的情況下有兩個對象。所以,這個規則適用於每個對象,但不適用於兩者。

0

關於您的疑問:

1)靜態同步方法使類級別的鎖。這裏什麼是類級鎖定的含義?如果一個線程已經被鎖定並且類級鎖被佔用,那麼爲什麼線程T2和T3開始執行?

static synchronized方法的情況下,只有一個線程在多個類的實例中獲取這些方法的鎖。如果您有兩個不同的實例:resource1resource2,對於Resource類,只有一個線程將成功鎖定m1()

如果resource1.m1()方法執行正在執行一個線程,其他線程不能執行resource2.m1()除非第一個線程完成執行m1()

由於方法m3()是非同步方法,因此任何線程都可以在不等待的情況下調用此方法並鎖定。

由於m2()m4()都是同步的,所以只有一個線程會成功鎖定同一對象(在您的示例中爲resource)。其他線程必須等到第一個線程完成synchrnozied方法的執行並釋放對象級鎖。

2)T4正在等待完成T2。雖然同步應用於兩種不同的方法,那麼爲什麼T4必須等待?如果對象級別鎖定在T2中工作,T4然後在上面說明爲什麼級別級別鎖定不起作用?

synchronized methods

使這些方法​​有兩個作用:

  1. 首先,這是不可能的同一對象上​​方法兩個調用交錯。當一個線程正在執行一個對象的​​方法時,所有其他調用同一對象的同步方法的線程將阻塞(掛起執行),直到第一個線程完成對象。其次,當一個同步方法退出時,它會自動建立一個與先前關聯的同步對象的任何後續調用同步方法。這保證了對所有線程都可見的對象狀態的更改。

static synchronized methods

線程獲取用於與類相關的Class對象固有鎖。因此,訪問類的static字段由與該類的任何實例的鎖截然不同的鎖控制。