簡體   English   中英

無法理解這種多線程異常行為

[英]Can't understand this multi-threading exception behavior

根據ReentrantLock.newCondition()的文檔,調用線程在調用信號方法之前需要擁有一個鎖:

如果在調用任何條件等待或信號方法時未持有此鎖,則會拋出 IllegalMonitorStateException。

事實上,這就是我在嘗試時看到的:

java.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1954)
    at PingPongPrinter_.printPing(PingPong2.java:35)
    at WorkerPing.run(PingPong2.java:53)
    at java.lang.Thread.run(Thread.java:748)

那么為什么這個限制存在於java.util.concurrent.locks.ReentrantLock中呢? 我相信C++ 沒有這樣的限制

回答原始問題

在發出信號之前,您正在解鎖與條件關聯的鎖。 從文檔:

在調用此方法時,實現可能(並且通常確實)要求當前線程持有與此條件關聯的鎖。 實現必須記錄此先決條件以及在未持有鎖時采取的任何操作。 通常,會拋出 IllegalMonitorStateException 等異常。

此外,僅鎖定修改您調節的值所需的時間。

void printPong() throws Exception {

  // wait for pong condition
  while (isPing) {
    blockPong.await();
  }

  rlock.lock();
  isPing = true; // modify value
  blockPing.signalAll(); // signal ping
  rlock.unlock();
  
  System.out.println("Pong");
}

void printPing() throws Exception {

  // wait for ping condition
  while (!isPing) {
    blockPing.await();
  }

  rlock.lock();
  isPing = false; // modify value
  blockPong.signalAll(); // signal pong
  rlock.unlock();

  System.out.println("Ping");

}

修改問題的答案

那么java.util.concurrent.locks.ReentrantLock為什么會有這個限制呢? 我相信C++中沒有這樣的限制。

因為ReentrantLock是互斥的。 它提供在任何給定時間對一個線程的訪問。 這是一個設計選擇。

在 C++ 中, std::condition_variable還要求您擁有該資源的互斥量才能發出信號。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM