多线程第三章-AQS及Lock锁

发布时间 2023-07-19 16:16:39作者: 浪成于微澜之间

前言

除了synchronized加锁之外,还有lock锁的方式,这俩种锁有什么区别尼?

synchronized

synchronized锁是非公平的锁,是独占的锁,属于抢占式的锁,而且根据synchronized在类中修饰的位置不同,锁的定义也不一样

lock

可以是公平锁也可以是非公平锁,默认实现是非公平的锁,他的实现方式与synchronized也不同,lock是一种可中断锁,使用lockSupport来做线程的中断,

lock实现方式

猜想:

  • 锁的互斥性,当一个线程在使用时,其他线程是无法使用的,需要一个status 来记录当前线程是否拥有锁,0(无锁), 1(有锁),
  • 没有抢占到锁的线程?-> 释放cpu资源,等待--->唤醒
  • 等待的线程如何存储?->使用那种数据结构来处理(能否插队)
  • 公平和非公平
  • 重入的特性(识别是否是同一个线程)

实现技术方案

  • volatile state (0无锁 ,1有锁,-1代表重入)
  • wait/notify |condition 唤醒线程? LockSupport.park /unpark
  • 双向链表存储等待线程
  • 逻辑层面实现公平与非公平
  • 早某一个地方存储当前获得锁线程的ID,判断下次抢占锁的线程是否是同一个。

lock的实现源码分析

public interface Lock {
    void lock();
}

lock的子类ReentrantLock类的构造函数,根据传值对于公平和非公平锁实现做了定义

 public ReentrantLock() {
        sync = new NonfairSync();
    }

    /**
     * Creates an instance of {@code ReentrantLock} with the
     * given fairness policy.
     *
     * @param fair {@code true} if this lock should use a fair ordering policy
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
NonfairSync(非公平锁)
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
             /**
              *  比较并设置值 CAS,这里调用的是AQS中的unsafe.compareAndSwapInt(this, stateOffset, expect, update);
              *  unsafe是个native调用的是机器内存值,这里的核心意思是,取用stateOffset当前的值,传入的值是0和1,拿
              *  0和stateOffset的值做比较,期望的值是0,然后将stateOffset的值更新成1,这里主要java底层借助计算机内存地址
              *  来做的,如何比较的期望值得到了,独占所标记住
              *
              */
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                //尝试获取锁,进入等待序列
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }
 public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
 final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            //获取AQS中volatile 的state值,再次使用CAS来获取锁,如果成功则标记
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {//当前线程是否为state=0的线程,将state标记改为1 
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

addWaiter(Node node)

private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }