如果说countDownLatch和lock 相似,semaphore和lock原理基本就是相同了。如果你对lock过程不了解,建议先看
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 GCfailed = 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没区别了。

本文详细比较了Semaphore与ReentrantLock的相似性和差异,包括它们的定义、获取资源的方式、释放资源的过程以及内部实现机制。揭示了两者在并发控制方面的联系与区别。
java Semaphore 源码解析及与lock对比&spm=1001.2101.3001.5002&articleId=76714268&d=1&t=3&u=8fece63209474737affe60fca0c88306)
1422

被折叠的 条评论
为什么被折叠?



