2016-08-20 55 views
0

我相信,這是一個簡單的問題,但我仍然不明白。說,我有以下代碼。調用同步方法的順序

Runnable objectRunnable = new Runnable() { 
    void run() { 
      synchronized(object) { 
       for (int i = 0; i < 5; i++) { 
        System.out.println("it's runnable"); 
        Thread.sleep(100); 
       } 
      } 
    } 
}; 

void doSomething() { 
    synchronized(object) { 
     for (int i = 0; i < 5; i++) { 
      System.out.println("it's doSomething"); 
      Thread.sleep(100); 
     } 
    } 
} 

synchronized (object) { 
    new Thread(objectRunnable).start(); 
} 
object.doSomething(); 

因此,輸出類似

it's doSomething 
it's doSomething 
it's doSomething 
it's doSomething 
it's doSomething 
it's runnable 
it's runnable 
it's runnable 
it's runnable 
it's runnable 

問題是,爲什麼doSomething()去線程之前?而且,如果我在同步塊之後多次調用對象方法,它們都會被隨後調用,並且只有程序返回到線程的內容。如果我用同步塊替換那個線程調用線,比如說調用一些模擬對象方法,那麼比一切都好,並按照指定的順序進行。

同步對象本身的方法在執行任何線程之前都有某種優先級,在此對象上同步?

+0

不幸的是,這段代碼不能編譯。 – tkausl

回答

1

你在這裏有一個競賽條件:由於圍繞它的創建,由於synchronized (object)的啓動,你的runnable被阻止在顯示器上等待。一旦創建runnable的線程釋放監視器,帶有runnable的新創建的線程就沒有機會抓住它,因爲同一個線程在doSomething()方法中再次重新輸入它。

如果在調用object.doSomething()

synchronized (object) { 
    new Thread(objectRunnable).start(); 
} 
Thread.sleep(100); // <<== Add this line 
object.doSomething(); 

打印的順序將反轉(demo)之前加入到Thread.sleep(100);通話。

it's runnable 
it's runnable 
it's runnable 
it's runnable 
it's runnable 
it's doSomething 
it's doSomething 
it's doSomething 
it's doSomething 
it's doSomething 
+0

它清除了一些東西,但仍然,爲什麼在同步創建runnable之後,線程不會被下一個調用?對我來說看起來合乎邏輯,因爲我們在代碼中的這個線程上調用了'start()',它在'doSomething()'之前,它們應該放在被調用方法堆棧的頂部,而不是讓當前線程搶他們之前的監視器 – idementia

+0

@idementia線程接下來會啓動,但它會立即被阻塞,因爲父線程仍然持有鎖。一旦父線程釋放鎖定,就可以抓取,但同一個線程更接近抓取它,因爲它已經在運行,而另一個線程被阻塞。 – dasblinkenlight

2

因爲主線程是第一個獲得鎖的線程。它可能是產生的線程,你可能無法確定,儘管這樣做的可能性很小,因爲調用start()之後需要一段時間才能真正開始運行。

關於你的問題的其餘部分,它太模糊,無法回答。