ReentrantLock是Java中提供的一种可重入的互斥锁,它具有与synchronized关键字相似的功能,但更加灵活和可控。下面是ReentrantLock底层实现原理的简要解释: ReentrantLock的底层实现主要依赖于AbstractQueuedSynchronizer(AQS)类。AQS是一个用于构建锁和其他同步器的框架,它提供了一种基于FIFO等待队列的同步机制。 ReentrantLock通过AQS实现了公平锁和非公平锁两种模式。在公平锁模式下,线程按照申请锁的顺序依次获取锁;而在非公平锁模式下,线程可以通过抢占的方式获取锁,不保证顺序。 当一个线程想要获取锁时,首先会尝试通过CAS(Compare and Swap)操作来修改AQS的状态值,将锁的状态设置为1,表示该线程已经获取到锁。如果CAS操作失败,说明有其他线程已经获取到了锁,当前线程会进入等待状态。 当一个线程释放锁时,它会调用AQS的release方法来释放锁资源。释放锁的过程主要包括将锁的状态设置为0、唤醒等待队列中的下一个线程,并将其从等待队列中移除。 ReentrantLock还支持可重入的特性,即同一个线程可以多次获取同一个锁,而不会造成死锁。ReentrantLock内部维护了一个计数器,记录了当前线程获取锁的次数。只有当计数器为0时,其他线程才能获取到锁。 总结来说,ReentrantLock底层实现通过AQS类提供了一种基于FIFO等待队列的同步机制,通过CAS操作来控制锁的获取和释放。同时,它还支持公平锁和非公平锁两种模式,并具备可重入的特性。这些特性使得ReentrantLock在多线程环境下能够更加灵活和可控地进行同步操作。
以下是一个使用ReentrantLock的示例代码:
javaCopy codeimport java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private static final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread thread1 = new Thread(new Worker());
Thread thread2 = new Thread(new Worker());
thread1.start();
thread2.start();
}
static class Worker implements Runnable {
@Override
public void run() {
lock.lock(); // 获取锁
try {
// 执行需要同步的操作
System.out.println("线程" + Thread.currentThread().getId() + "正在执行任务");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); // 释放锁
System.out.println("线程" + Thread.currentThread().getId() + "释放了锁");
}
}
}
}
上面的代码中,使用了一个静态的ReentrantLock对象作为锁。在Worker类的run方法中,首先使用lock.lock()
获取锁,然后执行需要同步的操作,最后使用lock.unlock()
释放锁。
两个线程都会执行相同的任务,但由于使用了ReentrantLock,只有一个线程可以获取到锁,另一个线程会在lock.lock()
处等待,直到第一个线程释放锁才能继续执行任务。
这样可以保证同一时刻只有一个线程在执行任务,实现了线程间的互斥操作。同时,由于ReentrantLock是可重入的,同一个线程可以多次获取同一个锁而不会造成死锁。