一、锁的实现(设计思维)
1.锁的互斥特性—>共享资源—>标记(0无锁,1代表有锁)
2.没有抢占到锁的线程?—>释放CPU资源【等待、唤醒】
3.等待的线程怎么存储?—>数据结构去存储一系列等待中的线程,FIFO(等待队列)
4.公平和非公平(能否插队)
5.重入的特性(识别是否同一个人?ThreadId)
二、技术方案
1.volatile state=0(无锁),1代表持有锁,>1代表重入锁
2.wait/notify | condition需要唤醒指定线程。[LockSupport.park(); —>unpark(thread)] unsafe类中提供的一个方法
3.双向链表
4.逻辑层面去实现
5.在某一个地方存储当前获得锁的线程的ID,判断下次抢占锁的线程是否同一个
三、源码
1.lock.lock()方法做了啥
2.lock.lock()调用了Sync(ReentrantLock类中的静态抽象类)的lock方法,sync是在ReentrantLock的构造方法中赋值的,无参构造函数中默认是非公平锁,有参的根据传入参数决定公平还是非公平。
3.调用非公平锁NonfairSync的lock()方法:
1 final void lock() { 2 //通过CAS乐观锁机制抢占互斥资源 3 if (compareAndSetState(0, 1))//将state改为1 4 //抢占成功,存储当前线程 5 setExclusiveOwnerThread(Thread.currentThread()); 6 else 7 //抢占失败的线程逻辑 8 acquire(1); 9 }
4.抢占失败的具体逻辑
1 public final void acquire(int arg) { 2 if (!tryAcquire(arg) && 3 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 4 selfInterrupt(); 5 }
1 //4.1tryAcquire()方法中的逻辑 2 final boolean nonfairTryAcquire(int acquires) { 3 //获得当前线程 4 final Thread current = Thread.currentThread(); 5 int c = getState(); 6 if (c == 0) {//无锁 7 if (compareAndSetState(0, acquires)) {//cas抢占锁 8 setExclusiveOwnerThread(current); 9 return true; 10 } 11 } 12 //判断重入? 13 else if (current == getExclusiveOwnerThread()) { 14 int nextc = c + acquires;//增加state的值 15 if (nextc < 0) // overflow 16 throw new Error("Maximum lock count exceeded"); 17 setState(nextc);//并不需要cas,因为已经是持有锁的状态 18 return true; 19 } 20 return false; 21 }
1 //4.2addWaiter()将未获得锁的线程加入到队列 2 private Node addWaiter(Node mode) { 3 Node node = new Node(Thread.currentThread(), mode); 4 // Try the fast path of enq; backup to full enq on failure 5 Node pred = tail; 6 if (pred != null) { 7 node.prev = pred; 8 if (compareAndSetTail(pred, node)) { 9 pred.next = node; 10 return node; 11 } 12 } 13 enq(node); 14 return node; 15 } 16 17 18 private Node enq(final Node node) { 19 for (;;) { 20 Node t = tail; 21 if (t == null) { // Must initialize 22 if (compareAndSetHead(new Node())) 23 tail = head; 24 } else { 25 node.prev = t; 26 if (compareAndSetTail(t, node)) { 27 t.next = node; 28 return t; 29 } 30 } 31 } 32 }
1 //4.3acquireQueued()去抢占锁或者阻塞 2 final boolean acquireQueued(final Node node, int arg) { 3 boolean failed = true; 4 try { 5 boolean interrupted = false; 6 for (;;) { 7 final Node p = node.predecessor(); 8 if (p == head && tryAcquire(arg)) {//前驱节点是否head&&抢占一次锁是否成功 9 setHead(node); 10 p.next = null; // help GC 11 failed = false; 12 return interrupted; 13 } 14 if (shouldParkAfterFailedAcquire(p, node) && 15 parkAndCheckInterrupt()) 16 interrupted = true; 17 } 18 } finally { 19 if (failed) 20 cancelAcquire(node); 21 } 22 } 23 24 private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { 25 int ws = pred.waitStatus; 26 if (ws == Node.SIGNAL) 27 return true; 28 if (ws > 0) {//取消状态的节点是大于0 29 //将取消状态的节点从链表中移除 30 do { 31 node.prev = pred = pred.prev; 32 } while (pred.waitStatus > 0); 33 pred.next = node; 34 } else { 35 //将前驱节点的waitStatus设置为-1 36 compareAndSetWaitStatus(pred, ws, Node.SIGNAL); 37 } 38 return false; 39 } 40 41 //阻塞当前线程 42 private final boolean parkAndCheckInterrupt() { 43 LockSupport.park(this); 44 return Thread.interrupted(); 45 } 46 47 48 final Node predecessor() throws NullPointerException { 49 Node p = prev; 50 if (p == null) 51 throw new NullPointerException(); 52 else 53 return p; 54 }
5.lock.unlock()做了啥?
调用aqs的release()方法
1 public final boolean release(int arg) { 2 if (tryRelease(arg)) { 3 Node h = head; 4 if (h != null && h.waitStatus != 0) 5 unparkSuccessor(h); 6 return true; 7 } 8 return false; 9 }
//5.1设置waitstate值,并将exclusiveOwnerThread置为null protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; }
1 //5.2唤醒一个队列中一个阻塞的线程 2 private void unparkSuccessor(Node node) { 3 int ws = node.waitStatus; 4 if (ws < 0) 5 //恢复成初始状态 6 compareAndSetWaitStatus(node, ws, 0); 7 Node s = node.next; 8 //去除无效节点 9 if (s == null || s.waitStatus > 0) { 10 s = null; 11 for (Node t = tail; t != null && t != node; t = t.prev) 12 if (t.waitStatus <= 0) 13 s = t; 14 } 15 if (s != null) 16 LockSupport.unpark(s.thread); 17 } 18 19 //脱离队列 20 private void setHead(Node node) { 21 head = node; 22 node.thread = null; 23 node.prev = null; 24 }
6.公平锁和非公平锁实现的区别
A.公平锁一开始没有抢占操作,而是直接进入acquire()方法
B.多了一个队列中有没有等待线程的判断
7.AQS队列是一个双向链表