美文网首页并发编程
Lock底层原理解析-AQS-双向链表-01

Lock底层原理解析-AQS-双向链表-01

作者: 愤怒的奶牛 | 来源:发表于2020-04-19 22:35 被阅读0次

1 话题引入-lock 简单使用

ReentrantLock

/**
 * j.u.c Lock 接口
 */
public class LockDemo {

    // 重入锁
    private Lock lock = new ReentrantLock();
    private int i = 0;

    public void add () {
        try {
            lock.lock();
            i = i+1;
            System.out.println(i);
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        LockDemo lockDemo = new LockDemo();
        for (int i = 0; i<10 ; i++) {
            new Thread(()->{
                lockDemo.add();
            }).start();
        }
    }
}

入手点 ReentrantLock

  • ReentrantLock 稍微看下jdk 的实现
* @since 1.5
 * @author Doug Lea
 */
public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    /** Synchronizer providing all implementation mechanics */
    private final Sync sync;

    /** 内部类
     * Base of synchronization control for this lock. Subclassed
     * into fair and nonfair versions below. Uses AQS state to
     * represent the number of holds on the lock.
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        /**
         * Performs {@link Lock#lock}. The main reason for subclassing
         * is to allow fast path for nonfair version.
         */
        abstract void lock();

         .............
/**
     * Sync object for non-fair locks
     */
    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() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

...............

/**
     * Creates an instance of {@code ReentrantLock}.
     * This is equivalent to using {@code ReentrantLock(false)}.
     */
    public ReentrantLock() { // 默认构造器
        sync = new NonfairSync();
    }
.......

上面是部分 代码,调用顺序

  1. new ReentrantLock() --> sync = new NonfairSync();
  2. NonfairSync extends Sync ;
  3. Sync extends AbstractQueuedSynchronizer ;
    到这里我们就 看到了 AQS
  • AbstractQueuedSynchronizer

AbstractQueuedSynchronizer 内部采用了 双向链表来存储 等待执行的线程。分析之前我们先来看一下 java 实现的双向链表:

  • 双向链表
/**
 * 双向链表
 */
public class Node {

    /**
     * 前一个结点
     */
    private Node pre;
    /**
     * 后一个节点
     */
    private Node next;
    /**
     * 头节点,指向第一个 节点
     */
    private Node header;
    /**
     * 尾节点,指向最后一个节点
     */
    private Node tail;
    /**
     * 节点数据
     */
    private Object data;


    public Node(Object data) {
        this.data = data;
    }
    public Node() {
    }


    /**
     * 向链表中添加一个节点,从尾部插入
     * @param newNode
     */
    public void addNode (Node newNode) {
        // 当前 尾部节点
       Node currentTail = this.tail;
       newNode.pre = currentTail;
       currentTail.next = newNode;
       this.tail = newNode;
    }

    public void print () {
        Node next = this.header.next;
        while (next != null) {
            System.out.println(next.data.toString());
            next = next.next;
        }
    }

    public static void main(String[] args) {
        Node list = new Node();
        Node header = new Node();
        // 初始化 链表, header == tail
        list.header = header;
        list.tail = header;

        list.addNode(new Node(1));
        list.addNode(new Node(2));
        list.addNode(new Node(4));
        list.addNode(new Node(3));
        //输出 
        list.print();


    }
}

我们温习了一些 双向链表,在分析 AQS 之前,还需要分析一个基础知识 CAS,下一篇文章我们就来学习CAS

相关文章

网友评论

    本文标题:Lock底层原理解析-AQS-双向链表-01

    本文链接:https://www.haomeiwen.com/subject/livibhtx.html