Java并发编程的艺术(八)——Java中的锁(3)

本文深入探讨了Java并发中的共享式与独占式锁的实现原理,详细解析了共享式获取锁与释放锁的过程,以及独占式超时获取同步状态的机制。文章对比了synchronized关键字与同步器提供的acquireInterruptibly方法在响应中断方面的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前边:阅读本文前推荐阅读Java中的锁(2),本文为该篇的延续。

3.共享式获取锁和释放锁

●共享式获取锁和独占式获取锁的主要区别在于在同一时刻能否有多个线程同时获得同步状态。通过调用同步器的acquireShared(int arg)方法可以共享式获取同步状态。

public final void acquireShared(int arg) {
    if(tryAcquireShared(arg) < 0)
        doAcquireShared(arg);
}

private void doAcquireShared(int arg) {
        //加入尾部队列
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        if (interrupted)
                            selfInterrupt();
                        failed = false;
                        return;
                    }
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
复制代码
  • 1.tryAcquireShared(int arg)方法尝试获取同步状态,且返回值为int型,当返回值大于等于0时,表示获取同步状态成功;若返回值小于0,则进入doAcquireShared(int arg)方法。

  • 2.在doAcquireShared(int arg)自旋的过程中,只有当前节点的前驱节点为头结点,才能尝试获取同步状态。若获取同步状态成功,则从自旋中退出。

●共享式锁通过调用releaseShared(int arg)方法释放同步状态。

public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }
复制代码
  • 1.该方法在释放同步状态成功后会唤醒后续处于等待状态的节点。
  • 2.因为可能存在多个线程同时释放同步状态的情况,tryReleaseShared(int arg)通过循环CAS的方法确保同步状态量能线程安全释放。

4. 独占式超时获取同步状态

●对于synchronized关键字来说,当线程因获取不到锁而synchronized被阻塞时,对线程进行中断,此时线程的中断标志位会被修改,当线程依旧阻塞,无法响应中断。

●对于同步器提供的acquireInterruptibly(int arg)方法来说,调用这个方法的线程因无法获得同步状态而阻塞在同步队列上时,仍然能够响应中断,响应中断的方式为抛出InterruptedException异常。

●超时获取同步状态的的过程可以视为可中断获取同步状态的"增强版",doAcquireNanos(int arg,long nanosTimeout)方法在支持中断响应的基础上,增加了超时等待的功能。

转载于:https://juejin.im/post/5d00d077e51d4510926a7b37

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值