ReetrantLock 是一个实现 Lock 接口的类。它提供了非常灵活的同步功能,这就是为什么它是Java中最常用的锁类。它对于螺纹的可靠和公平工作是必要的。在这里,线程是大操作的小子进程。在本文中,我们将学习 ReetrantLock 以及它们如何管理线程以便它们能够高效工作。

ReetrantLock 的工作

当多个线程尝试访问共享资源时, ReetrantLock 通过 lock()unlock() 方法限制一次对单个线程的访问。假设有三个人试图预订火车票。同时,三个人都会尝试访问预订系统,可能会出现两个人最终预订同一个座位的情况。可重入锁可以处理这种情况。

首先,三个人都会通过tryLock()方法请求获取预订系统。当获取预订系统后,它通过 lock() 方法限制特定的座位预订。预订后,该人将调用 unlock() 方法来释放所获取的锁。在资源繁忙之前,其他人将在队列中等待,释放锁后,他们将进入可运行状态。

ReetrantLock 尝试以公平的方式提供锁。我们可以设置线程可以获取锁的时间,并且可以确保等待时间最长的线程可以首先获取锁。默认情况下,锁是不公平的,为了使其公平,我们需要在其构造函数中传递布尔值 true

语法

ReentrantLock nameOflock = new  ReentrantLock(); 
// 默认为 false
Or,
ReentrantLock nameOflock = new  ReentrantLock(true); 
//我们可以让它成为现实 

锁是显式的,并且可以按任何顺序锁定或解锁。单个线程可以多次请求锁,这就是锁名称为可重入的原因。我们可以使用getHoldCount()方法来统计获取锁的次数。

无可重入锁的多线程示例

下面的示例说明了多线程在上面的代码中没有使用重入锁。我们创建了一个 Thrd 类,其中包含方法 operation() 来执行给定的任务。现在我们已经创建了三个线程类并调用 operation() 方法。在main()方法中,定义了三个线程类对象,并通过它们的start()方法来启动线程的执行。

示例

package com.yxjc123;

class Thrd {
   static void operation(int data) {    
      for(int i = 1; i <= 4; i++) {
        System.out.println(data++);
      }
   }
}
class Thrd1 extends Thread {
   //线程号1
   public void run() {
     Thrd.operation(1);
     //方法调用
   }
}
class Thrd2 extends Thread {
   //线程号2
   public void run() {
     Thrd.operation(5);  
     //方法调用
   }
}
class Thrd3 extends Thread {
   //线程号3
   public void run() {
     Thrd.operation(10);  
     //方法调用
   }
}
public class TestThread {
   public static void main(String args[]) {
     //为线程类创建对象
     Thrd1 oprt1 = new Thrd1();
     Thrd2 oprt2 = new Thrd2();  
     Thrd3 oprt3 = new Thrd3();
     //启动线程操作
     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.yxjc123;

import java.util.concurrent.locks.ReentrantLock;

class Thrd {
   //创建ReentrantLock类的对象
   private static ReentrantLock lockr = new  ReentrantLock();
   static void operation(int data) {
     //授予对锁的访问权限
     boolean lockAcquired = lockr.tryLock(); 
     if (lockAcquired) {
       try {
         lockr.lock(); 
         //给线程锁
         for(int i = 1; i <= 4; i++) {
            System.out.println(data++);
         }
         //检查锁计数
         System.out.println("Count of Lock: " + lockr.getHoldCount());
       } finally {
         lockr.unlock(); 
         //解锁
       }
     } else {
       System.out.println("I am in else block");
     }
   }
}
class Thrd1 extends Thread {
   //线程号1
   public void run() {
     Thrd.operation(1);
     //方法调用
   }
}
class Thrd2 extends Thread {
   //线程号2
   public void run() {
     Thrd.operation(5);  
     //方法调用
   }
}
class Thrd3 extends Thread {
   //线程号3
   public void run() {
     Thrd.operation(10);  
     //方法调用
   }
}
public class TestThread {
   public static void main(String args[]) {
     //为线程类创建对象
     Thrd1 oprt1 = new Thrd1();
     Thrd2 oprt2 = new Thrd2();  
     Thrd3 oprt3 = new Thrd3();
     //启动线程操作
     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 的多线程示例

以下示例说明了可重入锁的使用锁定上面的代码。我们创建了一个类Thrd,并在该线程内定义了一个公平值为 true 的 ReentrantLock 对象。方法 operation() 将 tryLock() 方法的布尔值存储到名为 lockAcquired 的变量中,该变量将检查是否有任何线程获取了锁。如果获取了锁,则使用 lock() 方法将锁授予该线程,然后该线程开始执行给定的任务。该任务将在 try 块中执行,并在 finally 块中使用 unlock() 方法释放锁。现在我们已经创建了三个线程类并调用 operation() 方法。在main()方法中,定义了三个线程类对象,并通过它们的start()方法来启动线程的执行。

示例

package com.yxjc123;

import java.util.concurrent.locks.ReentrantLock;

class Thrd {
   //创建ReentrantLock类的对象
   private static ReentrantLock lockr = new  ReentrantLock(true);
   static void operation(int data) {
     //授予对锁的访问权限
     boolean lockAcquired = lockr.tryLock(); 
     if (lockAcquired) {
       try {
         lockr.lock(); 
         //给线程锁
         for(int i = 1; i <= 4; i++) {
            System.out.println(data++);
         }
         //检查锁计数
         System.out.println("Count of Lock: " + lockr.getHoldCount());
       } finally {
         lockr.unlock(); 
         //解锁
       }
     } else {
       System.out.println("I am in else block");
     }
   }
}
class Thrd1 extends Thread {
   //线程号1
   public void run() {
     Thrd.operation(1);
     //方法调用
   }
}
class Thrd2 extends Thread {
   //线程号2
   public void run() {
     Thrd.operation(5);  
     //方法调用
   }
}
class Thrd3 extends Thread {
   //线程号3
   public void run() {
     Thrd.operation(10);  
     //方法调用
   }
}
public class TestThread {
   public static void main(String args[]) {
     //为线程类创建对象
     Thrd1 oprt1 = new Thrd1();
     Thrd2 oprt2 = new Thrd2();  
     Thrd3 oprt3 = new Thrd3();
     //启动线程操作
     oprt1.start();
     oprt2.start();  
     oprt3.start();
   }
} 

每次运行该程序时都会产生不同的结果 -

输出

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