jdk 源码分析(17)javaSemaphore 源码解析及与lock对比

xiaoxiao2021-02-28  104

如果说countDownLatch和lock 相似,semaphore和lock原理基本就是相同了。如果你对lock过程不了解,建议先看 (参考lock:jdk 源码分析(7)java ReentrantLock结构) 1)定义对比 semaphore public Semaphore(int permits) { sync = new NonfairSync(permits); } ReentrantLock public ReentrantLock() { sync = new NonfairSync(); } 默认都是使用非公平Sync,公平Sync是先到先得,非公平是先前获取一次值,然后才排队。 2)获取信号量和获取lock对比 acquire():会调用acquireSharedInterruptibly,首先会去判断是否state 是否已经达到能请求的数量,如果没有就直接返回false,让线程继续,否则会执行doAcquireSharedInterruptibly入队列中,然后park public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) doAcquireSharedInterruptibly(arg); } lock(),会调用这个方法 public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } 上面的 doAcquireSharedInterruptibly 方法,加入队列是为了unpark 的时候能找到线程。 private void doAcquireSharedInterruptibly(int arg) throws InterruptedException {           //加入队列 final Node node = addWaiter(Node.SHARED); boolean failed = true; try { for (;;) { final Node p = node.predecessor(); if (p == head) { int r = tryAcquireShared(arg); if (r >= 0) { setHeadAndPropagate(node, r); p.next = null; // help GC failed = false; return; } }                //park 一下 if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } } 3)release和unlock对比 release 会调用的方法,又是惊人的相似,先前改变state到可以使用的数目,然后去队列里释放相应数量的线程,不让他们等待了。 public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true; } return false; } unlock会调用的方法 public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } 4)对比release具体实现,是不是很相似。 上面的doReleaseShared方法 private void doReleaseShared() { for (;;) { Node h = head; if (h != null && h != tail) { int ws = h.waitStatus; if (ws == Node.SIGNAL) { if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) continue; // loop to recheck cases unparkSuccessor(h); } else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) continue; // loop on failed CAS } if (h == head) // loop if head changed break; } } lock的release。 public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } 总结: 应该可以说Semaphore 如果说是一种特殊的lock:(因为大家首先首先lock才这么说,应该是lock是一种特殊的Semaphore 1)lock 是独占,一人享用,而Semaphore是一个多人使用,lock是电影院的VIP单人间,Semaphore是大厅。 2)lock和Semaphore都需要排队,都有两种排队方式:公平和非公平。 3)lock和Semaphore都是改变state变量,只是lock争夺0变成1,而Semaphore是争一个非零的值,因此几率大很多。 4)如果初始是将permits也是就是state 置为1,那么Semaphore就和lock没区别了。
转载请注明原文地址: https://www.6miu.com/read-22309.html

最新回复(0)