2017-04-21 99 views
0

我得到兩個線程固定數量,遂以100個任務,裏面我困惑的Java線程池和ReentrantLock的

使用的鎖,故意離開它解鎖,運行這段代碼的結果是

排序號碼從1到99,這讓我感到困惑:

1)是否因爲線程被重用,以便同一個線程可以多次獲取它?

2)如果是這樣,鎖不阻塞線程,它仍然可以重用?鎖守只是其範圍內的界限。

請糾正我。

public class LockTest { 

    public static volatile int a = 1; 

    static final ReentrantLock lock = new ReentrantLock(); 

    public static void main(String[] args) { 
     ExecutorService executorService = Executors.newFixedThreadPool(2); 

     for (int k = 0; k < 100; k++) { 
      executorService.submit(new Runnable() { 
       @Override 
       public void run() { 
        lock.lock(); 
        System.out.println(a++); 
       } 
      }); 
     } 
     executorService.shutdown(); 
    } 
} 
+0

爲什麼沒有解鎖呼叫?永不解鎖的鎖的要點是什麼? –

+0

@ Sidias-Korrado是的,我讓它解鎖,我只是想弄清楚它是如何工作的 –

+1

你讓它鎖定,不解鎖。 –

回答

0

我會說你的分析是正確的。

  1. 是的,獲得鎖的第一個線程持有它。第二個線程在鎖定呼叫時阻塞。
  2. 是的,ReentrantLock的要點是同一個線程可以多次鎖定它。鎖保護不是線路,而是鎖定呼叫本身。

如果您想獲得其他線程必須獲取該鎖的能力,那麼每個lock()調用都必須有相應的unlock()電話。

1

如果您修改代碼,這樣你全部由自己來回答您的問題所需的信息:

public static void main(String[] args) { 
    ExecutorService executorService = newFixedThreadPool(2); 
    for (int k = 0; k < 100; k++) { 
     executorService.submit(() -> { 
      lock.lock(); 
      System.out.println(currentThread().getId() + 
          " hold count: " + lock.getHoldCount()); 
      System.out.println("a = " + a++); 
     }); 
    } 
    executorService.shutdown(); 
} 

輸出採樣

12 hold count: 1 
a = 1 
12 hold count: 2 
a = 2 
12 hold count: 3 
a = 3 
... 
12 hold count: 98 
a = 98 
12 hold count: 99 
a = 99 

正如你可以看到:

  • 你想輸出100數字,但你做o僅輸出99
  • 輸出顯示只有一個線程正在工作,因爲您永遠不會釋放鎖獲得的第一個線程。第二個線程等待獲取鎖定。
  • 因爲你使用了一個ReentrantLock第一個獲得該鎖的線程可能會繼續工作,因爲他已經擁有該鎖。
  • JVM將永遠不會關閉,因爲第一個線程永遠不會釋放鎖,因此第二個線程將永遠等待。

回答提問PO在評論

問這是一種可以預測的:在CachedThreadPool將動態創建新Threads的要求。發生什麼是:

  • 第一個線程將永久獲取鎖(因爲它永遠不會釋放它)。它會盡快處理提交的任務。
  • 當第一個線程正在處理時,CachedThreadPool將創建新線程來執行已提交但尚未處理的其餘任務。
  • 根據獲得鎖的第一個線程的速度,處理已提交的任務,這些任務尚未被調度給其他線程,您將以多個線程結束,並等待永久。
+0

thx,很明顯,但如果我將executorService更改爲Executors.newCachedThreadPool(),結果是不可預知的。 –