深入理解ReentrantLock的底层实现与应用

简介: 深入理解ReentrantLock的底层实现与应用

深入理解ReentrantLock的底层实现与应用

Java中的ReentrantLock是一个强大的可重入锁,提供了比传统的synchronized关键字更灵活的互斥性和可重入性。本文将深入探讨ReentrantLock的底层实现和一些常见的应用场景,并结合Java代码进行详细讲解。

1. ReentrantLock的基本使用

首先,让我们看一下ReentrantLock的基本用法:

import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
    private static final ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args) {
        // 启动两个线程演示ReentrantLock的基本用法
        new Thread(ReentrantLockExample::doSomething).start();
        new Thread(ReentrantLockExample::doSomething).start();
    }
    private static void doSomething() {
        lock.lock();
        try {
            // 临界区,线程在此处执行需要互斥的操作
            System.out.println(Thread.currentThread().getName() + " is in the critical section.");
        } finally {
            lock.unlock();
        }
    }
}

在上述代码中,我们创建了一个ReentrantLock实例lock,然后启动了两个线程,在doSomething方法中通过lock实现了对临界区的互斥访问。这是ReentrantLock的基本使用方式。

2. ReentrantLock的底层实现

2.1 Sync抽象类

ReentrantLock的底层实现依赖于AbstractQueuedSynchronizer(AQS)类。ReentrantLock包含一个抽象内部类Sync,它继承了AbstractQueuedSynchronizer,实现了锁的基本同步语义。

abstract static class Sync extends AbstractQueuedSynchronizer {
    // ...
}

2.2 FairSync和NonfairSync类

Sync有两个具体实现:FairSync和NonfairSync,分别对应于公平锁和非公平锁。公平锁会按照线程等待的顺序获取锁,而非公平锁则允许一个线程插队获取锁。

static final class NonfairSync extends Sync {
    // ...
}
static final class FairSync extends Sync {
    // ...
}

2.3 ReentrantLock构造方法

在ReentrantLock的构造方法中,根据用户的选择创建相应类型的Sync实例:

public ReentrantLock() {
    sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

2.4 lock和unlock操作

ReentrantLock的lock()方法和unlock()方法最终调用Sync中的相应方法。lock()方法尝试获取锁,如果当前线程已经持有锁,则增加锁的计数;如果锁已经被其他线程持有,则当前线程将被阻塞。unlock()方法用于释放锁。

public void lock() {
    sync.lock();
}
public void unlock() {
    sync.unlock();
}

3. 应用场景

3.1 可重入性

ReentrantLock支持可重入性,同一个线程可以多次获取锁,而不会发生死锁。这是通过Sync中的tryAcquire和tryRelease方法实现的。

public void nestedLockExample() {
    lock.lock();
    try {
        // some critical section
        nestedMethod();
    } finally {
        lock.unlock();
    }
}
private void nestedMethod() {
    lock.lock();
    try {
        // nested critical section
    } finally {
        lock.unlock();
    }
}

3.2 公平锁与非公平锁

ReentrantLock提供了公平锁和非公平锁的选择。在构造方法中传入true创建公平锁,传入false(或使用默认构造方法)创建非公平锁。

ReentrantLock fairLock = new ReentrantLock(true); // 公平锁
ReentrantLock nonfairLock = new ReentrantLock();   // 非公平锁

3.3 条件等待

ReentrantLock通过newCondition方法提供了Condition接口的实现,可以用于在锁上等待和唤醒线程。

Condition condition = lock.newCondition();
lock.lock();
try {
    while (someConditionIsTrue()) {
        condition.await();
    }
    // some critical section
} finally {
    lock.unlock();
}
相关文章
|
运维 监控 算法
稳定性保障6步走:高可用系统大促作战指南!
年年有大促,大家对于大促稳定性保障这个词都不陌生,业务场景尽管各不相同,“套路”往往殊路同归,全链路压测、容量评估、限流、紧急预案等,来来去去总少不了那么几板斧。跳出这些“套路”,回到问题的本质,我们为什么要按照这些策略来做?除了口口相传的历史经验,我们还能做些什么?又有什么理论依据?
稳定性保障6步走:高可用系统大促作战指南!
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
缓存 负载均衡 Java
2025春招 SpringCloud 面试题汇总
大家好,我是V哥。SpringCloud是面试中的重点,涵盖基础概念、组件细节、高级特性及性能优化等内容。为帮助大家更好地准备2025年的Spring Cloud面试,我整理了一系列常见面试题及答案,涉及服务注册与发现(Eureka)、配置管理(Spring Cloud Config)、负载均衡(Ribbon)、断路器(Hystrix)、微服务网关(Spring Cloud Gateway)等关键知识点。此外,还包括分布式事务管理、链路追踪(Sleuth+Zipkin)、安全性(OAuth2)以及性能优化和实践经验。希望这些内容能助你一臂之力,顺利通过面试。欢迎关注威哥爱编程,全栈之路就你行。
4408 24
|
canal 缓存 NoSQL
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
根据对一致性的要求程度,提出多种解决方案:同步删除、同步删除+可靠消息、延时双删、异步监听+可靠消息、多重保障方案
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
|
存储 安全 Java
ThreadLocal - 原理与应用场景详解
ThreadLocal是Java中用于实现线程隔离的重要工具,为每个线程提供独立的变量副本,避免多线程数据共享带来的安全问题。其核心原理是通过 ThreadLocalMap 实现键值对存储,每个线程维护自己的存储空间。ThreadLocal 广泛应用于线程隔离、跨层数据传递、复杂调用链路的全局参数传递及数据库连接管理等场景。此外,InheritableThreadLocal 支持子线程继承父线程的变量值,而 TransmittableThreadLocal 则解决了线程池中变量传递的问题,提升了多线程上下文管理的可靠性。深入理解这些机制,有助于开发者更好地解决多线程环境下的数据隔离与共享挑战。
2034 44
|
关系型数据库 MySQL 数据库
图解MySQL【日志】——两阶段提交
两阶段提交是为了解决Redo Log和Binlog日志在事务提交时可能出现的半成功状态,确保两者的一致性。它分为准备阶段和提交阶段,通过协调者和参与者协作完成。准备阶段中,协调者向所有参与者发送准备请求,参与者执行事务并回复是否同意提交;提交阶段中,若所有参与者同意,则协调者发送提交请求,否则发送回滚请求。MySQL通过这种方式保证了分布式事务的一致性,并引入组提交机制减少磁盘I/O次数,提升性能。
1324 5
图解MySQL【日志】——两阶段提交
|
存储 监控 算法
探索Java虚拟机:深入理解JVM内存模型和垃圾回收机制
在Java的世界中,JVM是核心所在,它不仅承载着代码的运行,还管理着内存资源。本文将带你深入了解JVM的内存模型和垃圾回收机制,通过具体数据与案例分析,揭示它们对Java应用性能的影响,并探讨如何优化JVM配置以提升效率。
407 27
|
网络协议 算法 网络性能优化
|
缓存 监控 安全
Spring AOP 详细深入讲解+代码示例
Spring AOP(Aspect-Oriented Programming)是Spring框架提供的一种面向切面编程的技术。它通过将横切关注点(例如日志记录、事务管理、安全性检查等)从主业务逻辑代码中分离出来,以模块化的方式实现对这些关注点的管理和重用。 在Spring AOP中,切面(Aspect)是一个模块化的关注点,它可以跨越多个对象,例如日志记录、事务管理等。切面通过定义切点(Pointcut)和增强(Advice)来介入目标对象的方法执行过程。 切点是一个表达式,用于匹配目标对象的一组方法,在这些方法执行时切面会被触发。增强则定义了切面在目标对象方法执行前、执行后或抛出异常时所
17943 4
|
Java 编译器 Spring
面试突击78:@Autowired 和 @Resource 有什么区别?
面试突击78:@Autowired 和 @Resource 有什么区别?
17598 7