2012-08-12 168 views
2

​​不會出現如我所預料的工作。它不應該使括號內的代碼原子相對於同一個對象的一個​​單獨的代碼塊​​?同步不同步

我發現它不同步所有我的代碼中。

private Object movementMutex_ = new Object();  

// Thread 
public void run() 
{ 
    while (run_) 
    { 
     synchronized(movementMutex_) 
     { 
      if (timeToMove_) 
      { 
       Log.v("meh", "timeToMove_ was true, moving"); 
       makeMove(); 
       Log.v("meh", "Move Complete. Setting timeToMove_ to false"); 
       timeToMove_ = false; 
       Log.v("meh", "timeToMove_ is now false"); 
      } 
     } 
    } 
} 


// Called by a different thread so that this thread knows when to make a move 
public void move() 
{ 
    Log.v("meh", "awaiting movementMutex in move()"); 
    // Synchronizing so that timeToMove_ doesn't get set true while in the middle of moving and thus setting it back false prematurely 
    synchronized(movementMutex_) 
    { 
     Log.v("meh", "move called, setting timeToMove_"); 
     timeToMove_ = true; 
     Log.v("meh", "timeToMove_ is now true"); 
    } 
} 

看着日誌打印輸出,我看到它們以意想不到的順序打印。根據我對同步的理解,大膽的陳述應該不會被非大膽的打印輸出解釋,但事實並非如此,我試圖避免的事情正在發生:我錯過了下一步,因爲我設置了它當它仍然是真實的並且立即將它變爲假的時候是真的。

08-12 10:47:19.860: V/meh(27639): awaiting movementMutex in move() 
08-12 10:47:19.985: V/meh(27639): move called, setting timeToMove_ 
08-12 10:47:19.985: V/meh(27639): timeToMove_ is now true 
08-12 10:47:19.985: V/meh(27639): **timeToMove_ was true, moving** 
08-12 10:47:20.352: V/meh(27639): awaiting movementMutex in move() 

這下一行應該是不可能的。它不等待運動Mutex!

08-12 10:47:20.352: V/meh(27639): move called, setting timeToMove_ 
08-12 10:47:20.360: V/meh(27639): timeToMove_ is now true 
08-12 10:47:20.360: V/meh(27639): **Move Complete. Setting timeToMove_ to false** 
08-12 10:47:20.360: V/meh(27639): **timeToMove_ is now false** 
+1

makeMove()函數是否調用move()函數?即,兩個同步塊是由同一個線程訪問的?這將解釋你所看到的。 – mah 2012-08-12 15:41:34

+0

你是說嵌套同步調用不會導致死鎖,而是會通過,因爲它已經有訪問權限?它不等同於一個互斥體的「wait()」調用嗎?如果是這樣,代碼進度可能會導致它間接調用它自己。如果這是正確的,隨時回答,我會標記它的答案。 – CodeMonkey 2012-08-12 15:52:24

+0

雖然很難找到有關嵌套同步調用的文檔,但是一個簡單的測試表明它確實忽略了它。它不會導致死鎖。所以我很確定這是我的問題。謝謝!對鎖重入(嵌套調用Sych發表) – CodeMonkey 2012-08-12 16:02:07

回答

1

正如在問題的評論中提到的,一個線程能夠重新輸入自己的同步鎖。 「makeMove()」函數調用實際上是調用「move()」的煽動者,這意味着它正在同一線程下執行,因此不會被鎖定。總之,下面的代碼不會導致死鎖;它會執行沒有問題,這是我所經歷的。

synchronized(movementMutex_) 
{ 
    synchronized(movementMutex_) 
    { 
     doSomething(); 
    } 
}