AQS

在这里插入图片描述

tryLock JDK实现:

在这里插入图片描述
在这里插入图片描述

Synchronized 和Lock 对比:

在这里插入图片描述

读写锁:

在这里插入图片描述

AQS:
https://blog.csdn.net/mulinsen77/article/details/84583716
关于AQS的概念这篇文章写的挺好的,可参考,本文主要是源码的阅读。

在这里插入图片描述
AQS 继承AbstractOwnableSynchronizer,在AbstractOwnableSynchronizer中有exclusiveOwnerThread这个变量用于记录独占锁属于哪个线程。

在这里插入图片描述
在这里插入图片描述

  • 加锁

在这里插入图片描述

  • 尝试加锁

在这里插入图片描述

  • 解锁:

在这里插入图片描述

  • 尝试解锁:

在这里插入图片描述
AQS 加锁和解锁的实现,但是没有实现尝试加锁和尝试解锁的方法。这里使用了模板模式,尝试加锁和尝试解锁的方法需要到子类中去实现。

以ReentrantLock为例子:

  • 非公平锁:

在这里插入图片描述
在这里插入图片描述

  • 公平锁:

在这里插入图片描述
公平锁和非公平锁的的抢锁的区别在于!hasQueuedPredecessors() 这里做了是否插队cas抢锁。具体看他的实现:

    public final boolean hasQueuedPredecessors() {
        // The correctness of this depends on head being initialized
        // before tail and on head.next being accurate if the current
        // thread is first in queue.
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }

请注意,这里返回的是否有前置任务。
请注意,这里返回的是否有前置任务。
请注意,这里返回的是否有前置任务。

非公平锁直接去抢锁,而公平锁去判断是否有前置任务,只有没有前置任务(也就是当前现在公平排队时时排到自己了)才去抢锁。

JDK这里的写法保证了性能,但是阅读起来有点难。(以后注意&& 和|| 使用时不仅仅是用于判断,还可以使用!& 和 || 直接 决定是否运行后部分的是否运行。这种写法阅读性较差。)

ReentrantReadWriteLock的公平机制:

在这里插入图片描述
ReentrantReadWriteLock

    static final class FairSync extends Sync {
        private static final long serialVersionUID = -2274990926593161451L;
        final boolean writerShouldBlock() {
            return hasQueuedPredecessors();
        }
        final boolean readerShouldBlock() {
            return hasQueuedPredecessors();
        }
    }

    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = -8159625535654395037L;
        final boolean writerShouldBlock() {
            return false; // writers can always barge
        }
        final boolean readerShouldBlock() {
            /* As a heuristic to avoid indefinite writer starvation,
             * block if the thread that momentarily appears to be head
             * of queue, if one exists, is a waiting writer.  This is
             * only a probabilistic effect since a new reader will not
             * block if there is a waiting writer behind other enabled
             * readers that have not yet drained from the queue.
             */
            return apparentlyFirstQueuedIsExclusive();
        }
    }

这里两个类定义了是否进行排队的判断。

        protected final boolean tryAcquire(int acquires) {
            /*
             * Walkthrough:
             * 1. If read count nonzero or write count nonzero
             *    and owner is a different thread, fail.
             * 2. If count would saturate, fail. (This can only
             *    happen if count is already nonzero.)
             * 3. Otherwise, this thread is eligible for lock if
             *    it is either a reentrant acquire or
             *    queue policy allows it. If so, update state
             *    and set owner.
             */
            Thread current = Thread.currentThread();
            int c = getState();
            int w = exclusiveCount(c);
            if (c != 0) {
                // (Note: if c != 0 and w == 0 then shared count != 0)
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // Reentrant acquire
                setState(c + acquires);
                return true;
            }
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }

这里关键的就是writerShouldBlock() 这里做了是否实现公平锁。和ReentrantLock 的判断类似,writerShouldBlock 返回false 直接走后部分代码,也就是插队抢锁(非公平)。返回ture 直接 尝试抢锁失败,

PS — JDK这里使用了模板模式,代码阅读难度大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值