2012-07-03 100 views
1

我有簡單的代碼:同步對象

public class testing { 
    private static Object objToSync = new Object(); 

    public static void main(String[] args) { 
     String obj1 = null; 
     synchronized(objToSync){ 
      System.out.println("something one");      
      doSomething(); 
      System.out.println("something three ");   
     } 

     doSomething();  
    } 

    private static void doSomething() { 
     synchronized(objToSync){ 
      System.out.println("something two"); 
     }  
    } 

我看了幾件事情,但是這一個仍然感到困惑。爲什麼主要的東西被調用?是不是應該等待同步的對象被解鎖?對不起,如果我聽起來很愚蠢,我只是困惑。

+0

*「爲什麼main中的doSomething被調用?」*有兩個調用'main'中的'doSomething',你指的是哪一個? –

+0

同步對象塊中的一個 – Madz

回答

10

是不是應該等到同步對象解鎖?

該鎖由線程舉行,讓你同步在兩次(在main第一次調用doSomething的情況下)沒有關係的事實,這是相同的線程上。如果另一個線程然後嘗試在objToSync進入​​塊,即其他線程會等到這個線程釋放所有的鎖。

您的代碼將做到這一點:

  1. 輸入main
  2. 獲取當前線程鎖objToSync對象
  3. 輸出 「的東西一個」
  4. 呼叫doSomething
  5. 得到一個當前線程的第二個鎖objToSync
  6. 輸出「東西兩個」
  7. 釋放第二鎖在當前線程上objToSync
  8. 返回從doSomething
  9. 輸出「東西三」
  10. 發佈第一鎖定爲當前線程上objToSync
  11. 呼叫doSomething
  12. objToSync
  13. 輸出「的東西兩個」
  14. 獲取新的鎖(對於同一個線程)
  15. 釋放,從doSomething
  16. 返回鎖定
  17. 返回從main

下面是一個使用兩個線程的例子:

public class SyncExample { 

    private static Object objToSync = new Object(); 

    public static final void main(String[] args) { 
     Thread second; 

     System.out.println("Main thread acquiring lock"); 
     synchronized (objToSync) { 
      System.out.println("Main thread has lock, spawning second thread"); 
      second = new Thread(new MyRunnable()); 
      second.start(); 
      System.out.println("Main thread has started second thread, sleeping a moment"); 
      try { 
       Thread.currentThread().sleep(250); 
      } 
      catch (Exception e) { 
      } 
      System.out.println("Main thread releasing lock"); 
     } 
     System.out.println("Main thread sleeping again"); 
     try { 
      Thread.currentThread().sleep(250); 
     } 
     catch (Exception e) { 
     } 
     System.out.println("Main thread waiting for second thread to complete"); 
     try { 
      second.join(); 
     } 
     catch (Exception e) { 
     } 
     System.out.println("Main thread exiting"); 
    } 

    static class MyRunnable implements Runnable { 

     public void run() { 
      System.out.println("Second thread running, acquiring lock"); 
      synchronized (objToSync) { 
       System.out.println("Second thread has lock, sleeping a moment"); 
       try { 
        Thread.currentThread().sleep(250); 
       } 
       catch (Exception e) { 
       } 
       System.out.println("Second thread releasing lock"); 
      } 
      System.out.println("Second thread is done"); 
     } 
    } 
} 

輸出:

Main thread acquiring lock 
Main thread has lock, spawning second thread 
Main thread has started second thread, sleeping a moment 
Second thread running, acquiring lock 
Main thread releasing lock 
Main thread sleeping again 
Second thread has lock, sleeping a moment 
Main thread waiting for second thread to complete 
Second thread releasing lock 
Second thread is done 
Main thread exiting
1

那是因爲你的程序只有1個線程 - 主線程。

5

鎖是reentrant所以如果某個線程擁有鎖定,它可以基於該鎖進入其他同步的塊。你的情況,你只有一個線程(主)和他正在做這樣的事情

synchronized(objToSync){ 
    System.out.println("something one");      
    synchronized(objToSync){ 
     System.out.println("something two"); 
    } 
    System.out.println("something three"); 
} 
1

鎖是相同的線程凹腔。這意味着已經獲得對象鎖定的線程可以訪問該對象的任何其他同步方法(或原子語句,如本例中所示)。一旦獲得該線程,該線程不需要再次獲得鎖定。