面试四、多线程之AQS、ReentrantLock

1、AQS:AbstractQueuedSynchronizer,抽象队列同步器。是java自带除synchronized关键字外的锁机制

2、是用来构建锁及其他同步器的重要框架,通过内置的CLH队列来完成资源获取线程的排队工作,将每条要去获取资源的线程分装成Node节点来实现锁的分配,有一个int变量来表示

  锁的持有状态(private volatile int state),通过cas来操作state完成状态修改(0-空闲;1-阻塞)

面试四、多线程之AQS、ReentrantLock

3、ReentrantLock节点AQS

  3.1、state有三个值:0-空闲;1-阻塞;大于1可重入

  3.2、n个线程进入,CLH队列中会有n+1个node节点,队列第一个是哨兵节点

  3.3、公平锁和非公平锁

    区别:

      公平锁每个线程进来会先判断当前自己是否位于队列首位,如果是则尝试获取锁(cas操作state),否则加入队列

      非公平锁新线程进来会先尝试获取锁(cas操作state)如果成功则将自己设置为第一个否则加入队列,可能导致有的线程长时间执行不到。

    ReentrantLock默认创建的是非公平锁

    ReentrantLock lock = new ReentrantLock(true) 创建的是公平锁。

    公平锁和非公平锁区别代码就在于公平锁多了65行!hasQueuedPredecessor(),此方法用于公平锁加锁时判断等待队列中是否存在有效节点

    非公平锁:

      36行:cas操作state,如成功则说明空闲,设置state为1,队列第一个设置为当前线程

      39行:如有阻塞,则调用acquire(1)

      83行:调用tryAcquire(),当前为非公平锁即调用42行->5行

      7行:获取state

      9行:如果cas操作state成功,则设置state为1,队列第一个设置为当前线程

      14行:如果当前线程又进来,则设置state=state+1(即可重入)

      84行:如果调用tryAcquire()失败即没有取到锁,则先调用addWaiter将当前线程封装成Node加入CLH链表,acquireQueued()

 

 1 /**
 2          * Performs non-fair tryLock.  tryAcquire is implemented in
 3          * subclasses, but both need nonfair try for trylock method.
 4          */
 5         final boolean nonfairTryAcquire(int acquires) {
 6             final Thread current = Thread.currentThread();
 7             int c = getState();
 8             if (c == 0) {
 9                 if (compareAndSetState(0, acquires)) {
10                     setExclusiveOwnerThread(current);
11                     return true;
12                 }
13             }
14             else if (current == getExclusiveOwnerThread()) {
15                 int nextc = c + acquires;
16                 if (nextc < 0) // overflow
17                     throw new Error("Maximum lock count exceeded");
18                 setState(nextc);
19                 return true;
20             }
21             return false;
22         }
23 
24 
25     /**
26      * Sync object for non-fair locks
27      */
28     static final class NonfairSync extends Sync {
29         private static final long serialVersionUID = 7316153563782823691L;
30 
31         /**
32          * Performs lock.  Try immediate barge, backing up to normal
33          * acquire on failure.
34          */
35         final void lock() {
36             if (compareAndSetState(0, 1))
37                 setExclusiveOwnerThread(Thread.currentThread());
38             else
39                 acquire(1);
40         }
41 
42         protected final boolean tryAcquire(int acquires) {
43             return nonfairTryAcquire(acquires);
44         }
45     }
46 
47     /**
48      * Sync object for fair locks
49      */
50     static final class FairSync extends Sync {
51         private static final long serialVersionUID = -3000897897090466540L;
52 
53         final void lock() {
54             acquire(1);
55         }
56 
57         /**
58          * Fair version of tryAcquire.  Don‘t grant access unless
59          * recursive call or no waiters or is first.
60          */
61         protected final boolean tryAcquire(int acquires) {
62             final Thread current = Thread.currentThread();
63             int c = getState();
64             if (c == 0) {
65                 if (!hasQueuedPredecessors() &&
66                     compareAndSetState(0, acquires)) {
67                     setExclusiveOwnerThread(current);
68                     return true;
69                 }
70             }
71             else if (current == getExclusiveOwnerThread()) {
72                 int nextc = c + acquires;
73                 if (nextc < 0)
74                     throw new Error("Maximum lock count exceeded");
75                 setState(nextc);
76                 return true;
77             }
78             return false;
79         }
80     }
81 
82     public final void acquire(int arg) {
83         if (!tryAcquire(arg) &&
84             acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
85             selfInterrupt();
86     }

 

面试四、多线程之AQS、ReentrantLock

上一篇:python redis cluster


下一篇:Python 中的 list、tuple、dict、set