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
广告