2015-08-17 61 views
2

我難以理解​​和重入鎖。這裏是小程序,我是用實驗:這些線程爲什麼不按順序運行?

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class Reentr { 

    public static void main(String[] args) { 
     ExecutorService eService = Executors.newFixedThreadPool(2); 
     for (int i = 1; i <= 2; i++) { 
      eService.execute(new process()); 
     } 

     try { 
      Thread.sleep(1); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     eService.shutdown(); 
    } 

} 

class process implements Runnable { 
    int count = 0; 

    @Override 
    public void run() { 

     processTest(); 
    } 

    public synchronized void processTest() { 
     try { 
      for (int i = 1; i <= 2; i++) { 
       count += i; 
       System.out.println("count value for " + Thread.currentThread().getName() + " is " + count); 
      } 
     } finally { 
      System.out.println("count for " + Thread.currentThread().getName() + " is " + count); 
     } 
    } 

} 

產量爲:

count value for pool-1-thread-2 is 1 
count value for pool-1-thread-1 is 1 
count value for pool-1-thread-2 is 3 
count for pool-1-thread-2 is 3 
count value for pool-1-thread-1 is 3 
count for pool-1-thread-1 is 3 

如果我們在輸出的兩個線程看到在synchronized塊。我的印象是一個線程必須完成synchronized方法的執行,然後其他線程纔會進入方法。

理想情況下,我期待結果是這樣的

count value for pool-1-thread-1 is 1 
count value for pool-1-thread-1 is 3 
count for pool-1-thread-1 is 3 
count value for pool-1-thread-2 is 1 
count value for pool-1-thread-2 is 3 
count for pool-1-thread-2 is 3 

我已經替換爲同步塊和重入鎖同步方法。但是,我仍然有相同的輸出。我錯過了什麼?

+0

您每次都有新的''process'實例。他們的關鍵部分沒有爭議。 – Keith

回答

1

兩個線程在同一個對象上不同步。

你有process兩個不同的實例(順便說一句,你應該總是命名以大寫字母類)。如果你想一個線程後,其他運行

public void processTest() { 
    synchronized(this) { 
    // etc.. 
    } 
} 

,他們必須在同一對象上進行同步:在​​關鍵字相當於。如果你這樣做,例如:

class process implements Runnable { 
    // note that this is static 
    private static final Object lock = new Object(); 

    public void processTest() { 
    synchronized(lock) { 
     // your code 
    } 
    } 
} 

然後你的代碼將有一個線程運行在另一個之後。另一種方法是將鎖傳入Object的構造函數或Semaphore的相同實例等。

+0

感謝您的迴應..我錯過了我每次都在創建新對象 – prred

1

當聲明實例方法​​時,它在對象實例上同步。由於您在每個循環迭代中運行new process(),因此對象實例不同,因此同步無意義。嘗試創建一個單一的process對象,並將其傳遞給您啓動的兩個線程。

當您這樣做時,還會將count實例變量移動到processTest方法中。這樣它將是線程安全的。

+0

感謝您的回覆..我錯過了我每次創建新對象 – prred

相關問題