AbstractQueuedSynchronizer--未完
来源:互联网 发布:c语言中的echo 编辑:程序博客网 时间:2024/06/03 05:26
1.1
//ReentrantLock.java//true为公平锁、false为非公平锁public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync();}//调用Sync的lockpublic void lock() { sync.lock();}//FairSync、NonfairSync继承自Sync。如果是公平锁,将调用FairSync的lock方法static final class FairSync extends Sync { final void lock() { acquire(1); }}
Sync继承自AbstractQueuedSynchronizer,acquire也是AbstractQueuedSynchronizer的方法
//AbstractQueuedSynchronizer.javapublic final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt();}
1、tryAcquire
//AbstractQueuedSynchronizer.java/*** Attempts to acquire in exclusive mode. This method should query* if the state of the object permits it to be acquired in the* exclusive mode, and if so to acquire it.* 独占模式下尝试获取锁,这个方法应该查询独占模式下这个对象是否能被获取* <p>This method is always invoked by the thread performing* acquire. If this method reports failure, the acquire method* may queue the thread, if it is not already queued, until it is* signalled by a release from some other thread. This can be used* to implement method {@link Lock#tryLock()}.* 这个方法经常通过线程去调用acquire方法。如果这个方法返回失败,将这个线程将加入队列,直到其他线程发起释放信号* <p>The default* implementation throws {@link UnsupportedOperationException}.** @param arg the acquire argument. This value is always the one* passed to an acquire method, or is the value saved on entry* to a condition wait. The value is otherwise uninterpreted* and can represent anything you like.* 这个值将被传到acquire方法,或者保存在entry中做条件等待。或者自己定义* @return {@code true} if successful. Upon success, this object has* been acquired.* 如果成功返回true* @throws IllegalMonitorStateException if acquiring would place this* synchronizer in an illegal state. This exception must be* thrown in a consistent fashion for synchronization to work* correctly.* @throws UnsupportedOperationException if exclusive mode is not supported*///这是一个虚方法,需要由子类实现具体的功能protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException();}
//ReentrantLock.javastatic final class FairSync extends Sync { /** * Fair version of tryAcquire. Don't grant access unless * recursive call or no waiters or is first. * 递归、没有其他线程或者是第一个线程调用,即成功获取锁才返回true */ //acquires是调用lock方法通过acquire传的值 protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); //AbstractQueuedSynchronizer中的state标记,使用compareAndSetState赋值 int c = getState(); //如果没有线程获得锁 if (c == 0) { //如果没有其他线程竞争锁 且锁没被占用,将获得锁对象 if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { //将获得锁的线程赋给锁对象 setExclusiveOwnerThread(current); return true; } } //如果当前线程持有锁,可以再次获取锁 即重入 else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); //将state的值+acquires并赋给state setState(nextc); return true; } return false; }} 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()); }
2、addWaiter
//如果能一次添加元素成功,直接返回。否则自旋直到添加成功private Node addWaiter(Node mode) { //构造Node,传入当前线程 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; } //插入队尾 private Node enq(final Node node) { for (;;) { Node t = tail; //如果链表空 则新建一个head //能进到这里 说明已经有其他线程正在占有锁,所以这个new Node()就代表那个占有锁的线程 if (t == null) { // Must initialize if (compareAndSetHead(new Node())) tail = head; //如果链表不为空,则一直尝试加入链表尾 } else { node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } }
3、acquireQueued
/** * Acquires in exclusive uninterruptible mode for thread already in * queue. Used by condition wait methods as well as acquire. * * @param node the node * @param arg the acquire argument * @return {@code true} if interrupted while waiting */ final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { //p= node的前一个元素 final Node p = node.predecessor(); //如果前一个Node是head 说明前一条线程可能正在占有锁而且随时可能释放 此时当前线程去尝试获取锁 if (p == head && tryAcquire(arg)) { //如果获取锁成功,将本线程所在节点置为队列头 setHead(node); //将前一个节点的所有引用置为null,方便回收前一个节点 p.next = null; // help GC failed = false; return interrupted; } //判断是否需要阻塞,然后阻塞,并判断线程是否中断 if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } }
//定义在Node中waitStatus的状态值 //线程已经取消 static final int CANCELLED = 1; //后续的线程需要唤醒 static final int SIGNAL = -1; //线程正在等待 static final int CONDITION = -2; /** * waitStatus value to indicate the next acquireShared should * unconditionally propagate */ static final int PROPAGATE = -3; //pred=node.prev //判断是否需要阻塞 private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus; if (ws == Node.SIGNAL) /* * This node has already set status asking a release * to signal it, so it can safely park. * 如果这个node已经设置了一个请求释放的信号,可以安全的放置 */ return true; if (ws > 0) { /* * Predecessor was cancelled. Skip over predecessors and * indicate retry. */ //跳过前面设有取消标记的等待线程 do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); pred.next = node; } else { /* * waitStatus must be 0 or PROPAGATE. Indicate that we * need a signal, but don't park yet. Caller will need to * retry to make sure it cannot acquire before parking. * waitStatus是0或PROPAGATE,表明需要信号,但是又不想阻塞。调用者需要再次确认在阻塞之前不能获取锁 */ compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; }
/** * Convenience method to park and then check if interrupted * * @return {@code true} if interrupted */ private final boolean parkAndCheckInterrupt() { LockSupport.park(this); //被唤醒后 判断线程是否被中断 return Thread.interrupted(); } public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); //调用park阻塞线程 UNSAFE.park(false, 0L); setBlocker(t, null); }
//取消正在获取锁的尝试 private void cancelAcquire(Node node) { // Ignore if node doesn't exist if (node == null) return; node.thread = null; // Skip cancelled predecessors //跳过已经取消的线程元素 Node pred = node.prev; while (pred.waitStatus > 0) node.prev = pred = pred.prev; // predNext is the apparent node to unsplice. CASes below will // fail if not, in which case, we lost race vs another cancel // or signal, so no further action is necessary. // //pred的next元素不一定是node Node predNext = pred.next; // Can use unconditional write instead of CAS here. // After this atomic step, other Nodes can skip past us. // Before, we are free of interference from other threads. //设置为取消状态,其他元素可以跳过这个元素 node.waitStatus = Node.CANCELLED; // If we are the tail, remove ourselves. //如果当前元素在末尾,直接删除 if (node == tail && compareAndSetTail(node, pred)) { compareAndSetNext(pred, predNext, null); } else { // If successor needs signal, try to set pred's next-link // so it will get one. Otherwise wake it up to propagate. int ws; //如果其他元素需要SIGNAL标记, if (pred != head && ((ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) && pred.thread != null) { Node next = node.next; //移除被标记为cancel的node前面的元素 if (next != null && next.waitStatus <= 0) compareAndSetNext(pred, predNext, next); } else { //唤醒线程 unparkSuccessor(node); } node.next = node; // help GC } } private void unparkSuccessor(Node node) { /* * If status is negative (i.e., possibly needing signal) try * to clear in anticipation of signalling. It is OK if this * fails or if status is changed by waiting thread. */ int ws = node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 0); /* * Thread to unpark is held in successor, which is normally * just the next node. But if cancelled or apparently null, * traverse backwards from tail to find the actual * non-cancelled successor. */ Node s = node.next; //如果next元素为null或者状态是取消, if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) LockSupport.unpark(s.thread); }
阅读全文
0 0
- AbstractQueuedSynchronizer--未完
- AbstractQueuedSynchronizer
- AbstractQueuedSynchronizer
- AbstractQueuedSynchronizer
- AbstractQueuedSynchronizer
- AbstractQueuedSynchronizer
- AbstractQueuedSynchronizer
- AbstractQueuedSynchronizer
- AbstractQueuedSynchronizer
- AbstractQueuedSynchronizer
- 未完
- 未完
- 未完
- 未完!
- 未完
- 未完
- 未完
- 未完
- Hadoop2.7.3环境下Sqoop1.99.5安装
- 小女孩海边捡来"脏石头"竟是一内含珍珠的稀罕红鲍
- 新的起点
- Android Activity生命周期以及Fragment生命周期的区别与分析
- Visual Studio 快捷键更改和设置
- AbstractQueuedSynchronizer--未完
- 分布式,集群概念简介
- 关于在 Virtualenv环境下安装Flask_SQLAlchemy报错
- com.seventh7.plugin.mybatis IDEA插件初始化失败,导致IDEA不能启动
- springmvc+ajax时controller中return跳转不了前台页面
- Android第七天
- R生成latex表格代码
- Linux/Unix系统编程-基本概念
- TFIDF算法Java实现