博客
关于我
ReentrantLock源码分析
阅读量:772 次
发布时间:2019-03-23

本文共 3364 字,大约阅读时间需要 11 分钟。

ReentrantLock和AQS技术深入解析

ReentrantLock是Java Concurrent包中提供的一种可重入锁,主要用于实现多线程环境下的资源同步。可重入锁的意义在于允许持有锁的一线程多次获取锁资源,而无需每次都释放锁,这避免了死锁的发生,极大提升了多线程应用的性能和可靠性。

AQS(AbstractQueuedSynchronizer)简介

ReentrantLock的实现基础是AQS,一个抽象的同步队列器,用于实现两种同步模式:排他(独占)模式和共享模式。排他模式下,AQS提供了可重入锁的实现机制,而共享模式适用于线程之间可以并发访问的场景。

AQS的核心结构包括一个状态变量state、持有锁的线程Thread exclusiveOwnerThread,以及一个双端队列用于管理等待锁的线程。

核心变量分析

  • state:用于表示锁的状态,值为0时无持有者,非0时表示有持有者。可重入锁情况下,state会递增,表示同一线程多次获取锁资源。
  • exclusiveOwnerThread:记录当前持有锁的线程,初始值为null。

等待队列管理

AQS使用双端队列实现等待队列,头尾节点通过Node对象表示。每个节点包含:

  • waitStatus:等待状态,初始值为0。可能状态包括:

    • SIGNAL(-1):指示当前节点需要唤醒。
    • CANCELLED(1):当前线程已取消排队。
  • Thread thread:对应等待的线程。

节点的插入和移除通过自旋锁实现,以确保在高并发情况下操作的原子性。

ReentrantLock实现细节

ReentrantLock本身通过内部类Sync(继承自AQS)实现,可分为公平锁和非公平锁两种类型。

  • 非公平锁:在获取锁时不考虑等待队列,直接抢占锁或进入队列。
  • 公平锁:先检查等待队列头部是否有其他线程(FIFO),再进行锁获取。

锁的获取过程(详解)

非公平锁(NonfairSync)

非公平锁的lock()方法:

public final void lock() {    if (compareAndSetState(0, 1)) {        setExclusiveOwnerThread(Thread.currentThread());    } else {        acquire(1);    }}public final void acquire(int arg) {    if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))        selfInterrupt();}
  • tryAcquire:尝试通过compareAndSet获取锁,成功则更新exclusiveOwnerThread;失败则加入等待队列。
  • acquireQueued:将线程挂入队列,并阻塞直到唤醒或中断。

公平锁(FairSync)

public final void lock() {    acquire(1);}public final boolean tryAcquire(int acquires) {    if (getQueue().hasQueuedPredecessors()) {        if (compareAndSetState(0, acquires)) {            setExclusiveOwnerThread(Thread.currentThread());            return true;        }    }    return false;}
  • tryAcquire:先检查等待队列是否有前驱节点,若有则需要排队,否则直接获取锁。

锁的释放(unlock()方法)

public void unlock() {    sync.release(1);}public boolean release(int arg) {    if (tryRelease(arg)) {        unparkSuccessor(head);        return true;    }    return false;}protected final boolean tryRelease(int releases) {    if (Thread.currentThread() != getExclusiveOwnerThread())        throw new IllegalMonitorStateException();    int c = getState() - releases;    if (c == 0) {        setExclusiveOwnerThread(null);        setState(c);        return true;    }    setState(c);    return true;}
  • release:尝试释放锁,唤醒等待队列的头节点。

中断处理(lockInterruptibly()方法)

public void lockInterruptibly() throws InterruptedException {    sync.acquireInterruptibly(1);}public final void acquireInterruptibly(int arg) throws InterruptedException {    if (Thread.interrupted())        throw new InterruptedException();    if (!tryAcquire(arg))        doAcquireInterruptibly(arg);}private void doAcquireInterruptibly(int arg) throws InterruptedException {    final Node node = addWaiter(Node.EXCLUSIVE);    boolean failed = true;    try {        for (;;) {            if (node.predecessor() == head && tryAcquire(arg)) {                setHead(node);                failed = false;                return;            }            if (shouldParkAfterFailedAcquire(node.predecessor(), node) &&                parkAndCheckInterrupt())                throw new InterruptedException();        }    } finally {        if (failed)            cancelAcquire(node);    }}
  • doAcquireInterruptibly:处理中断情况,挂起线程并在收到中断时重置中断标记。

总结

ReentrantLock通过AQS实现了高效的可重入锁机制,在多线程环境中提供了强大的同步能力。其设计巧妙地平衡了并发性能和正确性,适用于广泛的多线程场景。理解AQS内部工作原理是掌握ReentrantLock关键的前提,以便优化应用性能并避免潜在的死锁问题。

AQS的核心在于通过等待队列管理线程同步,支持多种同步模式的实现。非公平锁通过自旋锁实现快速入队,适合并发率高但并发竞争宽松的场景;而公平锁则确保等待线程按FIFO顺序获取锁,适合更严格的公平要求。ReentrantLock的设计为多线程开发提供了可靠的基础,值得深入研究和应用。

转载地址:http://czhzk.baihongyu.com/

你可能感兴趣的文章
Multisim中555定时器使用技巧
查看>>
MySQL CRUD 数据表基础操作实战
查看>>
multisim变压器反馈式_穿过隔离栅供电:认识隔离式直流/ 直流偏置电源
查看>>
mysql csv import meets charset
查看>>
multivariate_normal TypeError: ufunc ‘add‘ output (typecode ‘O‘) could not be coerced to provided……
查看>>
MySQL DBA 数据库优化策略
查看>>
multi_index_container
查看>>
mutiplemap 总结
查看>>
MySQL Error Handling in Stored Procedures---转载
查看>>
MVC 区域功能
查看>>
MySQL FEDERATED 提示
查看>>
mysql generic安装_MySQL 5.6 Generic Binary安装与配置_MySQL
查看>>
Mysql group by
查看>>
MySQL I 有福啦,窗口函数大大提高了取数的效率!
查看>>
mysql id自动增长 初始值 Mysql重置auto_increment初始值
查看>>
MySQL in 太多过慢的 3 种解决方案
查看>>
Mysql Innodb 锁机制
查看>>
MySQL InnoDB中意向锁的作用及原理探
查看>>
MySQL InnoDB事务隔离级别与锁机制深入解析
查看>>
Mysql InnoDB存储引擎 —— 数据页
查看>>