ReentrantLock
是一个实现了 Lock
接口的类。它提供了同步功能的强大灵活性,这也是为什么它是 Java 中最常用的锁类。为了确保线程可靠且公平地工作是必要的。在这里,线程是大操作中的小子过程。在本文中,我们将学习 ReentrantLock
及其如何管理线程以便它们能高效地工作。
ReentrantLock 的工作原理
当多个线程试图访问共享资源时,ReentrantLock
通过 lock()
和 unlock()
方法限制一次只有一个线程访问。假设三个人同时尝试预订火车票,所有三个人都会尝试同时访问订票系统,可能会导致两个人最终预订了同一个座位。ReentrantLock
可以处理这种情况。
首先,所有人都会请求通过 tryLock()
方法获取订票系统。当一个人获得了订票系统后,则通过 lock()
方法限制特定座位的预订。在完成预订后,该人将调用 unlock()
方法释放已获取的锁。直到资源忙于处理时,其他人会在队列中等待他们的轮次,而在锁释放后,他们将进入可运行状态。
ReentrantLock
尝试公平地提供锁。我们可以设置线程可以获取锁的时间长度,并且它确保等待时间最长的线程可能首先获得锁。默认情况下,锁是非公平的,要使其公平,我们需要在其构造函数中传递布尔值 true
。
语法
ReentrantLock nameOflock = new ReentrantLock();
或者,
ReentrantLock nameOflock = new ReentrantLock(true);
锁是显式的,并且可以以任意顺序锁定或解锁。单个线程可以多次请求锁,这就是锁的名字中有“Reentrant”(可重入)的原因。我们可以使用 getHoldCount()
方法来计算一个锁被获取了多少次。
没有 ReentrantLock 的多线程
以下示例说明了在上述代码中没有使用 ReentrantLock
的多线程。我们创建了一个类 Thrd
,其中包含一个 operation()
方法来执行给定的任务。现在我们创建了三个线程类并调用 operation()
方法。在 main()
方法中定义了三个线程类的对象,并调用它们的 start()
方法以启动线程的执行。
没有 ReentrantLock 的多线程示例
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 {
public void run() {
Thrd.operation(1);
}
}
class Thrd2 extends Thread {
public void run() {
Thrd.operation(5);
}
}
class Thrd3 extends Thread {
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
带有 ReentrantLock 的多线程
以下示例说明了上述代码中 ReentrantLock
的使用。我们在 Thrd
类内部定义了一个 ReentrantLock
对象。operation()
方法将 tryLock()
方法的布尔值存储到名为 lockAcquired
的变量中,该变量将检查是否有线程获取了锁。如果锁被获取,则使用 lock()
方法给予该线程锁,然后线程开始执行给定的任务。任务将在 try
块中执行,并在 finally
块中使用 unlock()
方法释放锁。现在我们创建了三个线程类并调用 operation()
方法。在 main()
方法中定义了三个线程类的对象,并调用它们的 start()
方法以启动线程的执行。
带有 ReentrantLock 的多线程示例
package com.tutorialspoint;
import java.util.concurrent.locks.ReentrantLock;
class Thrd {
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 {
public void run() {
Thrd.operation(1);
}
}
class Thrd2 extends Thread {
public void run() {
Thrd.operation(5);
}
}
class Thrd3 extends Thread {
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
带有 ReentrantLock 为真值的多线程
以下示例说明了上述代码中 ReentrantLock
的使用。我们在 Thrd
类内部定义了一个带有公平值为 true
的 ReentrantLock
对象。operation()
方法将 tryLock()
方法的布尔值存储到名为 lockAcquired
的变量中,该变量将检查是否有线程获取了锁。如果锁被获取,则使用 lock()
方法给予该线程锁,然后线程开始执行给定的任务。任务将在 try
块中执行,并在 finally
块中使用 unlock()
方法释放锁。现在我们创建了三个线程类并调用 operation()
方法。在 main()
方法中定义了三个线程类的对象,并调用它们的 start()
方法以启动线程的执行。
带有 ReentrantLock 为真值的多线程示例
package com.tutorialspoint;
import java.util.concurrent.locks.ReentrantLock;
class Thrd {
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 {
public void run() {
Thrd.operation(1);
}
}
class Thrd2 extends Thread {
public void run() {
Thrd.operation(5);
}
}
class Thrd3 extends Thread {
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