淘先锋技术网

首页 1 2 3 4 5 6 7

Semaphore 概述

  • Semaphore 来自于 JDK 1.5JUC 包,直译过来就是 信号量,被作为一种多线程并发控制工具来使用
  • Semaphore 可以控制同时访问共享资源的线程个数,线程通过 acquire() 方法获取一个信号量,信号量减一,如果没有就等待;通过 release() 方法释放一个信号量,信号量加一
  • 它通过控制信号量的总数量,以及每个线程所需获取的信号量数量,进而控制多个线程对共享资源访问的并发度,以保证合理的使用共享资源。相比 synchronized 和独占锁一次只能允许一个线程访问共享资源,功能更加强大,有点类似于共享锁

Semaphore 源码

类图

在这里插入图片描述
可以很明显的看出来 SemaphoreCountDownLatch 一样都是直接使用 AQS 实现的。区别就是 Semaphore 还分别实现了公平模式 FairSync 和非公平模式 NonfairSync 两个内部类

构造器及内部类

public class Semaphore implements java.io.Serializable {
    private static final long serialVersionUID = -3222578661600680210L;
    
    private final Sync sync;
	
	/*创建具有给定的信号量数和非公平模式的 Semaphore*/
	public Semaphore(int permits) {
    	sync = new NonfairSync(permits);
	}

 	/*创建具有给定的信号量数和给定的公平设置的 Semaphore*/
	public Semaphore(int permits, boolean fair) {
    	sync = fair ? new FairSync(permits) : new NonfairSync(permits);
	}

	/*非公平模式的实现*/
	static final class NonfairSync extends Sync {
    	private static final long serialVersionUID = -2694183684443567898L;

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

 	/*公平模式的实现*/
	static final class FairSync extends Sync {
    	private static final long serialVersionUID = 2014338818796000944L;

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

 	/*信号量的同步实现。 使用 AQS 的state状态表示信号量。子分类为公平和非公平模式*/
	abstract static class Sync extends AbstractQueuedSynchronizer {
    	private static final long serialVersionUID = 1192457210091910933L;
    
    	Sync(int permits) {
        	//被设置为state值
        	setState(permits);
   		}
    	//......
	}
}	
  • 实际上公平与非公平只是在获取信号量的时候得到体现,它们的释放信号量的方法都是一样的,这就类似于 ReentrantLock:公平与非公平只是在获取锁的时候得到体现,它们的释放锁的方法都是一样的
  • 在构造器部分,如同 CountDownLatch 构造函数传递的初始化计数个数 count 被赋给了AQSstate 状态变量一样,Semaphore 的信号量个数 permits 同样赋给了AQSstate
  • 在创建 Semaphore 时可以使用一个 fair 变量指定是否使用公平策略,默认是非公平模式。公平模式会确保所有等待的获取信号量的线程按照先进先出的顺序获取信号量,而非公平模式则没有这个保证。非公平模式的吞吐量比公平模式的吞吐量要高,而公平模式则可以避免线程饥饿