Semaphore源码分析

70 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

继承关系

Semaphore只实现了Serializable接口

public class Semaphore implements java.io.Serializable

内部类

Semaphore同样存在三个内部类,Sync、NonfairSync、FairSync,其中Sync继承了AQS,而NonfairSync和FairSync分别继承了Sync,所以从根本上来说Semaphore的实现还是依赖于AQS

abstract static class Sync extends AbstractQueuedSynchronizer{}

static final class NonfairSync extends Sync{}

static final class FairSync extends Sync 

构造函数

创建具有给定许可数和非公平设置的信号量。 Semaphore(int permits)

public Semaphore(int permits) {
    sync = new NonfairSync(permits);
}

Semaphore(int permits, boolean fair)

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

核心函数 -- acquire

此方法从信号量获取一个(多个)许可,在提供一个许可前一直将线程阻塞,或者线程被中断

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

后续调用流程和CountDownLatch的调用流程一致,不在赘述 大致调用流程如下

image.png

核心函数 -- release

此方法释放一个(多个)许可,将其返回给信号量

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

后续调用流程和CountDownLatch的调用流程一致,不在赘述 大致调用流程如下

image.png

Semaphore示例

import java.util.concurrent.Semaphore;

class MyThread extends Thread {
    private Semaphore semaphore;
    
    public MyThread(String name, Semaphore semaphore) {
        super(name);
        this.semaphore = semaphore;
    }
    
    public void run() {        
        int count = 3;
        System.out.println(Thread.currentThread().getName() + " trying to acquire");
        try {
            semaphore.acquire(count);
            System.out.println(Thread.currentThread().getName() + " acquire successfully");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release(count);
            System.out.println(Thread.currentThread().getName() + " release successfully");
        }
    }
}

public class SemaphoreDemo {
    public final static int SEM_SIZE = 10;
    
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(SEM_SIZE);
        MyThread t1 = new MyThread("t1", semaphore);
        MyThread t2 = new MyThread("t2", semaphore);
        t1.start();
        t2.start();
        int permits = 5;
        System.out.println(Thread.currentThread().getName() + " trying to acquire");
        try {
            semaphore.acquire(permits);
            System.out.println(Thread.currentThread().getName() + " acquire successfully");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release();
            System.out.println(Thread.currentThread().getName() + " release successfully");
        }      
    }
}