Java 教程

Java 控制語句

面向物件程式設計

Java 內建類

Java 檔案處理

Java 錯誤和異常

Java 多執行緒

Java 同步

Java 網路

Java 集合

Java 介面

Java 資料結構

Java 集合演算法

高階 Java

Java 雜項

Java API 和框架

Java 類引用

Java 有用資源

Java - 可重入監視器



Java 中的可重入監視器

ReetrantLock 是一個實現 Lock 介面的類。它提供了 同步 功能,具有很強的靈活性,因此它是 Java 中使用最多的鎖類。它對於執行緒的可靠和 公平工作 是必要的。這裡,執行緒是大操作的小子程序。在本文中,我們將學習 ReetrantLock 以及它們如何管理執行緒以使其能夠高效地工作。

ReetrantLock 的工作原理

多個執行緒 嘗試訪問共享資源時,ReetrantLock 透過 lock()unlock() 方法一次限制一個執行緒訪問。假設有三人試圖預訂火車票。同時,這三個人都會嘗試訪問預訂系統,可能會發生兩個人最終預訂了同一個座位的情況。Reetrant Lock 可以處理這種情況。

首先,這三個人都會透過 tryLock() 方法請求獲取預訂系統。當一個人獲取預訂系統後,它會透過 lock() 方法限制特定的座位預訂。預訂後,該人將呼叫 unlock() 方法釋放獲取的鎖。在資源繁忙期間,其他人將排隊等待輪到他們,並在鎖釋放後進入可執行狀態。

ReetrantLock 試圖以公平的方式提供鎖。我們可以設定執行緒可以獲取鎖的時間長度,並且它還可以確保等待時間最長的執行緒可能首先獲取鎖。預設情況下,鎖是不公平的,要使其公平,我們需要在其建構函式中傳遞布林值 true

語法

ReentrantLock nameOflock = new  ReentrantLock(); 
// by default false
Or,
ReentrantLock nameOflock = new  ReentrantLock(true); 
// we can make it true

鎖是顯式的,可以按任何順序鎖定或解鎖。單個執行緒可以多次請求鎖,這就是鎖名稱為可重入的原因。我們可以使用 getHoldCount() 方法計算鎖被獲取的次數。

沒有可重入鎖的多執行緒

以下示例說明了在上述程式碼中未使用可重入鎖的多執行緒。我們建立了一個名為 Thrd 的類,其中包含一個名為 operation() 的方法來執行給定的任務。現在,我們建立了三個執行緒類並呼叫 operation() 方法。在 main() 方法中,定義了執行緒類的三個物件,並使用它們的 start() 方法 來啟動執行緒的執行。

沒有可重入鎖的多執行緒示例

package com.tutorialspoint;

class Thrd {
   static void operation(int data) {    
      for(int i = 1; i <= 4; i++) {
        System.out.println(data++);
      }
   }
}
class Thrd1 extends Thread {
   // thread number 1 
   public void run() {
     Thrd.operation(1);
     // method calling  
   }
}
class Thrd2 extends Thread {
   // thread number 2 
   public void run() {
     Thrd.operation(5);  
     // method calling
   }
}
class Thrd3 extends Thread {
   // thread number 3
   public void run() {
     Thrd.operation(10);  
     // method calling
   }
}
public class TestThread {
   public static void main(String args[]) {
     // creating object for thread class
     Thrd1 oprt1 = new Thrd1();
     Thrd2 oprt2 = new Thrd2();  
     Thrd3 oprt3 = new Thrd3();
     // Starting the thread operation
     oprt1.start();
     oprt2.start();  
     oprt3.start();
   }
}

每次執行此程式時,這都會產生不同的結果 -

輸出

1
2
3
4
10
11
12
13
5
6
7
8

使用可重入鎖的多執行緒

以下示例說明了在上述程式碼中使用可重入鎖。我們建立了一個名為 Thrd 的類,並在該執行緒內部,我們定義了一個 ReentrantLock 的物件。一個名為 operation() 的方法將 tryLock() 方法的布林值儲存到名為 lockAcquired 的變數中,該變數將檢查鎖是否被任何執行緒獲取。如果獲取了鎖,則使用 lock() 方法將鎖授予該執行緒,然後執行緒開始執行給定的任務。該任務將在 try 塊中執行,並且鎖將在 finally 塊中使用 unlock() 方法釋放。現在,我們建立了三個執行緒類並呼叫 operation() 方法。在 main() 方法中,定義了執行緒類的三個物件,並使用它們的 start() 方法來啟動執行緒的執行。

使用可重入鎖的多執行緒示例

package com.tutorialspoint;

import java.util.concurrent.locks.ReentrantLock;

class Thrd {
   // creating object of ReentrantLock class
   private static ReentrantLock lockr = new  ReentrantLock();
   static void operation(int data) {
     // give access to lock
     boolean lockAcquired = lockr.tryLock(); 
     if (lockAcquired) {
       try {
         lockr.lock(); 
         // giving lock to thread
         for(int i = 1; i <= 4; i++) {
            System.out.println(data++);
         }
         // checking lock count
         System.out.println("Count of Lock: " + lockr.getHoldCount());
       } finally {
         lockr.unlock(); 
         // unlocking the lock 
       }
     } else {
       System.out.println("I am in else block");
     }
   }
}
class Thrd1 extends Thread {
   // thread number 1 
   public void run() {
     Thrd.operation(1);
     // method calling  
   }
}
class Thrd2 extends Thread {
   // thread number 2 
   public void run() {
     Thrd.operation(5);  
     // method calling
   }
}
class Thrd3 extends Thread {
   // thread number 3
   public void run() {
     Thrd.operation(10);  
     // method calling
   }
}
public class TestThread {
   public static void main(String args[]) {
     // creating object for thread class
     Thrd1 oprt1 = new Thrd1();
     Thrd2 oprt2 = new Thrd2();  
     Thrd3 oprt3 = new Thrd3();
     // Starting the thread operation
     oprt1.start();
     oprt2.start();  
     oprt3.start();
   }
}

每次執行此程式時,這都會產生不同的結果 -

輸出

I am in else block
5
6
7
8
Count of Lock: 2
I am in else block

將可重入鎖設定為 True 的多執行緒

以下示例說明了在上述程式碼中使用 Reentrant Lock 的方法。我們建立了一個類Thrd,並在該執行緒內部,我們定義了一個 ReentrantLock 物件,其公平值為 true。方法 operation() 將tryLock()方法的布林值儲存到名為lockAcquired的變數中,該變數將檢查鎖是否被任何執行緒獲取。如果獲取了鎖,則使用lock()方法將鎖授予該執行緒,然後執行緒開始執行給定的任務。該任務將在 try 塊中執行,並在 finally 塊中使用unlock()方法釋放鎖。現在我們建立了三個執行緒類並呼叫了operation()方法。在 main() 方法中,定義了三個執行緒類的物件,並呼叫它們的start()方法以啟動執行緒的執行。

Reentrant Lock 為 True 的多執行緒示例

package com.tutorialspoint;

import java.util.concurrent.locks.ReentrantLock;

class Thrd {
   // creating object of ReentrantLock class
   private static ReentrantLock lockr = new  ReentrantLock(true);
   static void operation(int data) {
     // give access to lock
     boolean lockAcquired = lockr.tryLock(); 
     if (lockAcquired) {
       try {
         lockr.lock(); 
         // giving lock to thread
         for(int i = 1; i <= 4; i++) {
            System.out.println(data++);
         }
         // checking lock count
         System.out.println("Count of Lock: " + lockr.getHoldCount());
       } finally {
         lockr.unlock(); 
         // unlocking the lock 
       }
     } else {
       System.out.println("I am in else block");
     }
   }
}
class Thrd1 extends Thread {
   // thread number 1 
   public void run() {
     Thrd.operation(1);
     // method calling  
   }
}
class Thrd2 extends Thread {
   // thread number 2 
   public void run() {
     Thrd.operation(5);  
     // method calling
   }
}
class Thrd3 extends Thread {
   // thread number 3
   public void run() {
     Thrd.operation(10);  
     // method calling
   }
}
public class TestThread {
   public static void main(String args[]) {
     // creating object for thread class
     Thrd1 oprt1 = new Thrd1();
     Thrd2 oprt2 = new Thrd2();  
     Thrd3 oprt3 = new Thrd3();
     // Starting the thread operation
     oprt1.start();
     oprt2.start();  
     oprt3.start();
   }
}

每次執行此程式時,這都會產生不同的結果 -

輸出

I am in else block
I am in else block
5
6
7
8
Count of Lock: 2
廣告