java信号量
阅读原文时间:2023年07月08日阅读:3

维基百科解释的信号量概念如下

信号量(英语:semaphore)又称为信号标,是一个同步对象,用于保持在0至指定最大值之间的一个计数值。当线程完成一次对该semaphore对象的等待(wait)时,该计数值减一;当线程完成一次对semaphore对象的释放(release)时,计数值加一。当计数值为0,则线程等待该semaphore对象不再能成功直至该semaphore对象变成signaled状态。semaphore对象的计数值大于0,为signaled状态;计数值等于0,为nonsignaled状态.

semaphore对象适用于控制一个仅支持有限个用户的共享资源,是一种不需要使用忙碌等待(busy waiting)的方法。

信号量的概念是由荷兰计算机科学家艾兹赫尔·戴克斯特拉(Edsger W. Dijkstra)发明的,广泛的应用于不同的操作系统中。在系统中,给予每一个行程一个信号量,代表每个行程目前的状态,未得到控制权的行程会在特定地方被强迫停下来,等待可以继续进行的讯号到来。如果信号量是一个任意的整数,通常被称为计数讯号量(Counting semaphore),或一般讯号量(general semaphore);如果信号量只有二进位的0或1,称为二进位讯号量(binary semaphore)。在linux系统中,二进位讯号量(binary semaphore)又称互斥锁(Mutex)。

********************************************************

博客正文:Java中的信号量是类Semaphore源码如下

package java.util.concurrent;
import java.util.Collection;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class Semaphore implements java.io.Serializable {
private static final long serialVersionUID = -3222578661600680210L;
/** All mechanics via AbstractQueuedSynchronizer subclass */
private final Sync sync;

abstract static class Sync extends AbstractQueuedSynchronizer {  
    private static final long serialVersionUID = 1192457210091910933L;

    Sync(int permits) {  
        setState(permits);  
    }

    final int getPermits() {  
        return getState();  
    }

    final int nonfairTryAcquireShared(int acquires) {  
        for (;;) {  
            int available = getState();  
            int remaining = available - acquires;  
            if (remaining < 0 ||  
                compareAndSetState(available, remaining))  
                return remaining;  
        }  
    }

    protected final boolean tryReleaseShared(int releases) {  
        for (;;) {  
            int current = getState();  
            int next = current + releases;  
            if (next < current) // overflow  
                throw new Error("Maximum permit count exceeded");  
            if (compareAndSetState(current, next))  
                return true;  
        }  
    }

    final void reducePermits(int reductions) {  
        for (;;) {  
            int current = getState();  
            int next = current - reductions;  
            if (next > current) // underflow  
                throw new Error("Permit count underflow");  
            if (compareAndSetState(current, next))  
                return;  
        }  
    }

    final int drainPermits() {  
        for (;;) {  
            int current = getState();  
            if (current == 0 || compareAndSetState(current, 0))  
                return current;  
        }  
    }  
}

/\*\*  
 \* NonFair version  
 \*/  
static final class NonfairSync extends Sync {  
    private static final long serialVersionUID = -2694183684443567898L;

    NonfairSync(int permits) {  
        super(permits);  
    }

    protected int tryAcquireShared(int acquires) {  
        return nonfairTryAcquireShared(acquires);  
    }  
}

/\*\*  
 \* Fair version  
 \*/  
static final class FairSync extends Sync {  
    private static final long serialVersionUID = 2014338818796000944L;

    FairSync(int permits) {  
        super(permits);  
    }

    protected int tryAcquireShared(int acquires) {  
        for (;;) {  
            if (hasQueuedPredecessors())  
                return -1;  
            int available = getState();  
            int remaining = available - acquires;  
            if (remaining < 0 ||  
                compareAndSetState(available, remaining))  
                return remaining;  
        }  
    }  
}

/\*\*  
 \* Creates a {@code Semaphore} with the given number of  
 \* permits and nonfair fairness setting.  
 \*  
 \* @param permits the initial number of permits available.  
 \*        This value may be negative, in which case releases  
 \*        must occur before any acquires will be granted.  
 \*/  
public Semaphore(int permits) {  
    sync = new NonfairSync(permits);  
}

public Semaphore(int permits, boolean fair) {  
    sync = fair ? new FairSync(permits) : new NonfairSync(permits);  
}

public void acquire() throws InterruptedException {  
    sync.acquireSharedInterruptibly(1);  
}

public void acquireUninterruptibly() {  
    sync.acquireShared(1);  
}

public boolean tryAcquire() {  
    return sync.nonfairTryAcquireShared(1) >= 0;  
}

public boolean tryAcquire(long timeout, TimeUnit unit)  
    throws InterruptedException {  
    return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));  
}

public void release() {  
    sync.releaseShared(1);  
}

public void acquire(int permits) throws InterruptedException {  
    if (permits < 0) throw new IllegalArgumentException();  
    sync.acquireSharedInterruptibly(permits);  
}

public void acquireUninterruptibly(int permits) {  
    if (permits < 0) throw new IllegalArgumentException();  
    sync.acquireShared(permits);  
}

public boolean tryAcquire(int permits) {  
    if (permits < 0) throw new IllegalArgumentException();  
    return sync.nonfairTryAcquireShared(permits) >= 0;  
}

public boolean tryAcquire(int permits, long timeout, TimeUnit unit)  
    throws InterruptedException {  
    if (permits < 0) throw new IllegalArgumentException();  
    return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));  
}

public void release(int permits) {  
    if (permits < 0) throw new IllegalArgumentException();  
    sync.releaseShared(permits);  
}

public int availablePermits() {  
    return sync.getPermits();  
}

public int drainPermits() {  
    return sync.drainPermits();  
}

protected void reducePermits(int reduction) {  
    if (reduction < 0) throw new IllegalArgumentException();  
    sync.reducePermits(reduction);  
}

public boolean isFair() {  
    return sync instanceof FairSync;  
}

public final boolean hasQueuedThreads() {  
    return sync.hasQueuedThreads();  
}

public final int getQueueLength() {  
    return sync.getQueueLength();  
}

protected Collection<Thread> getQueuedThreads() {  
    return sync.getQueuedThreads();  
}

public String toString() {  
    return super.toString() + "\[Permits = " + sync.getPermits() + "\]";  
}  

}

它有两个构造,单一参数的是构造一出一个不公平锁的信号量类,两个参数的第一个参数是指定信号数,第二个是是否使用公平锁。关于详细的介绍查看Java并发之Semaphore

它的简单使用如下

定义一个信号量对象semaphore,在线程执行之前通过semaphore.acquire()进行信号量的获取,如果得到permit信号当前线程就会执行,否则当前线程不会被执行,线程执行之后一定要release()释放信号。

当初始化的信号量是0时,可以通过当前信号量的对象调用release(int a)放入两个信号量。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器