探討Java中的多執行緒概念 - foojay

發表於2021-05-12

解釋Java程式語言中多執行緒的複雜性,讓我們從快速概覽和理解核心概念開始。

 

作業系統中的執行緒概念

  • 執行緒:執行緒是輕量級程式,但它在多個方面與程式不同。執行緒的主要特徵是它建立併發執行過程的感覺。它可以有效地分配工作並執行單個任務,可以用於排程和非同步執行任務,它具有比程式更有效的上下文切換機制,並且它與其他執行緒共享記憶體空間,但是可以擁有自己的儲存空間
  • 關鍵部分Critical Section:程式碼的關鍵部分被標識為焦點區域,多個執行緒可以同時訪問該焦點區域並可以修改狀態。由於共享資源時會同時進行修改,因此需要對訪問進行控制。
  • 訊號量:訊號量是一種資源計數,可用於控制對共享資源的訪問,尤其是在多執行緒環境中。
  • 互斥量:互斥量是一種同步結構,僅允許一個執行緒一次使用資源並擁有與之相關的所有權。
  • 監控器:一種同步構造,它允許相互排斥並具有等待條件為真的能力。
  • 死鎖:在訪問程式碼的關鍵部分時,可能存在多個執行緒訪問多個共享資源的情況。在這種情況下,當單個執行緒需要訪問共享資源時,它可能首先需要釋放當前持有的共享資源。關於同一資源的另一個同時執行的執行緒也可能是正確的。當無法實現這種互斥時,將導致死鎖。
  • 死鎖預防:防止死鎖情況發生的技術構成了死鎖預防。
  • 死鎖處理:死鎖的檢測及其消除構成了死鎖處理。
  • 重入:在不完成其先前呼叫的情況下可以重新輸入方法或子例程的情況。 

探討Java中的多執行緒概念  - foojay

 

Java中執行緒介面或類

  • 執行緒:解釋了執行緒類的重要方法,並在程式碼示例中顯示了用法。即使是有經驗的Java程式設計師在多執行緒中,最令人困惑和常見的錯誤是理解鎖。在每種方法中,我都提供了共享物件上的鎖定狀態。
  • Runnable:建立執行緒的另一種方法是實現此介面。可以通過實現Runnable介面或擴充套件Thread類來在Java中建立執行緒。程式設計師將必須重寫此介面中的run()方法以實現邏輯。
  • start(),會獲取鎖定狀態;這是用來排程執行緒執行的方法。一旦計劃好並且CPU週期可用,該執行緒就會實際執行。
  • run(),會獲取鎖定;Thread執行時會隱式呼叫它以開始執行執行緒。
  • yield(),鎖定保持;此方法將控制權產生或轉移給具有相同優先順序的另一個執行緒。它不能保證將控制權轉移到哪個執行緒,也不能保證。下面的程式碼片段還顯示瞭如何通過擴充套件Thread類來建立Thread。
  • sleep(),鎖定會保持;此方法使當前正在執行的執行緒在給定的時間段內暫停執行。時間段以毫秒為單位指定。它丟擲一箇中斷的異常,該異常需要由程式設計師處理。
  • join(),鎖定會保持;這導致執行模式,其中所有執行緒都在當前執行緒的末尾加入。換句話說,當前執行緒在切換到另一個執行緒之前已完成。它將引發一箇中斷的異常,程式設計師必須處理該異常。
  • suspend(),已棄用。
  • resume(),已棄用;不建議使用這些執行緒方法,因為它可能導致死鎖和凍結程式。當必須恢復掛起執行緒的執行緒需要在呼叫resume()之前訪問該掛起執行緒持有的共享資源或鎖時,尤其如此。
  • stop(),已棄用;不建議使用此執行緒方法,因為由於損壞的物件而產生的狀態不一致。我不提供程式碼示例,因為它是非常直接的用法–但即使使用非常舊的編譯器版本,我也不建議使用這些方法。

 

Java中的物件

Java中的Object類固有地包含可以控制對此物件的訪問的方法,尤其是在共享或多執行緒應用程式中。

  • wait(),當前物件鎖定已釋放,已持有其他鎖定;wait()方法使當前執行緒暫停執行並進入等待狀態。它還釋放它在當前物件上持有的鎖,但保留其他物件上的所有其他鎖。
  • notify(),任意等待執行緒處於鎖定狀態;notify()方法通知正在等待獲取當前共享物件上的鎖的任意執行緒。
  • notifyAll(),任意等待的執行緒正在鎖定狀態;此方法的notifyAll()對應物件通知所有正在等待獲取共享庫上的鎖的執行緒。
  • 關於鎖的注意事項:每當您想到Java中的鎖或監視器時,都可以使用此原則:執行緒進行的任何併發修改都不應導致物件損壞。唯一的例外是wait()和notify()機制,它們可能導致交換或切換控制之前更改共享資源或物件。損壞的物件是指狀態發生不希望的或可破壞的更改的物件。
  • 同步synchronized:在Java中,sync關鍵字用於控制對程式碼關鍵部分的訪問。另外,它是Java中的執行緒監視器的實現。sync關鍵字既可以應用於靜態方法,也可以應用於例項級方法或塊。當執行緒進入同步的塊或方法時,它將獲得對該類或物件的鎖定。對於靜態同步方法,單個鎖儲存在類級別,並且不同於每個類例項儲存的例項級鎖。sync關鍵字在共享資源上提供了必要的互斥。只能在同步塊或方法中呼叫wait(),notify()和notifyAll()。Java不固有地支援互斥物件。

案例研究:設計一個多執行緒系統,該系統的共享資源只能採用兩個值。0或1。它應該有兩種方法,一種用於遞增和遞減的方法,由兩個執行緒同時呼叫。其中一個執行緒只能不斷增加,而另一個只能不斷減少。它們的操作應互斥。

解決方案:它是生產者-消費者問題的簡化版本:

package org.csi_india.programming.workbench.multithreading;

public class CSIDecrementer implements Runnable {

  CSISharedObject csiSharedObject;

  CSIDecrementer(CSISharedObject csiSharedObject) {
    this.csiSharedObject=csiSharedObject;
  }

  public void run() {
    while(true) csiSharedObject.decrementerAccess();
  }

}
package org.csi_india.programming.workbench.multithreading;

public class CSIIncrementer implements Runnable {

  CSISharedObject csiSharedObject;

  CSIIncrementer(CSISharedObject csiSharedObject) {
    this.csiSharedObject=csiSharedObject;
  }

  public void run() {
    while(true) csiSharedObject.incrementerAccess();
  }

}
package org.csi_india.programming.workbench.multithreading;

public class CSIWorkbench extends Thread {

  public static void main(String args) {
    CSISharedObject csiShared=new CSISharedObject();
    Thread csiThread01=new Thread(new CSIIncrementer(csiShared));
    csiThread01.start();
    Thread csiThread02=new Thread(new CSIDecrementer(csiShared));
    csiThread02.start();
  }

}
package org.csi_india.programming.workbench.multithreading;

public class CSISharedObject {
   // access from within this class only
   private int;
   public synchronized void decrementerAccess() {
   try {
     if (x = ) {
       x--;
       notify();
     } else {
       wait();
     }
   } catch (InterruptedException e) {
       System.out.println("thread interrupted");
   }
}

public synchronized void incrementerAccess() {
   try {
     if (x = ) {
     x++;
     notify();
      } else {
        wait();
      }
   } catch (InterruptedException e) {
      System.out.println("thread interrupted");
   }
}

 

以下是為Java中的非同步任務執行提供了更細化或受控的訪問。

  • Callable:類似於Runnable的另一個類,其例項可能由另一個執行緒執行。
  • Executors:用於建立執行緒池的幫助程式介面。
  • ExecutorService:非同步任務執行器,可用於提交Runnable或Callable任務以執行,然後通過Future物件跟蹤它們的狀態。
  • Future:物件從任務提交返回到非同步任務執行器,可使用該執行器監視任務狀態。
  • AtomicInteger: Java中的一種Integer物件,它使用硬體指令執行併發的無鎖更新。
  • Condition:條件將物件監視方法(wait,notify和notifyAll()分解為不同的物件,從而通過將它們與任意Lock實現結合使用,從而使每個物件具有多個等待集。對於同步的方法和語句,Condition代替了Object監視器方法的使用,Condition是Java介面。
  • signal():喚醒一個等待的執行緒。
  • signalAll():喚醒所有等待的執行緒。
  • await():使當前執行緒等待,直到被訊號通知或中斷為止。鎖定:與使用同步方法和語句相比,鎖定實現提供了更廣泛的鎖定操作。鎖是一個介面。
  • ReentrantLock:可重入互斥鎖,其基本行為與隱式監視器鎖相同。它是Lock的具體實現。

 

相關文章