Java中的信号量Semaphore

2019-12-18   阅读(221)  

信号量的实现模型一般包括:1个计数器、1个等待队列、3个方法(需要保证原子性)

JDK 中 Semaphore 是基于 AbstractQueuedSynchronizer 实现,可以指定是否公平​

 

信号量 Semaphore 实现的伪代码:

class Semaphore{
	//计数器
	int count;
	
	//等待队列
	Queue queue;
	
	//初始化
	Semaphore(int c){
		this.count=c;
	}
	
	//获取许可证
	void acquire(){
		count--;
		if(count<0){
			//将当前线程插入等待队列
			//阻塞当前线程
		}
	}
	
	//获取许可证
	void release(){
		count++;
		if(count<=0) {
			//移除等待队列中的某个线程
			//唤醒某个线程
		}
	}
}

 

使用信号量实现互斥锁效果:

package constxiong.interview;

import java.util.concurrent.Semaphore;

/**
 * 测试使用信号量实现锁的效果
 * @author ConstXiong
 * @date 2019-12-18 14:18:47
 */
public class TestSemaphore {

	private static int count;
	
	private static Semaphore semaphore = new Semaphore(1); 
	
	public static void main(String[] args) {
		for (int i = 0; i < 100; i++) {
			new Thread(() -> {
				add();
				System.out.println(count);
			}).start();
		}
	}
	
	private static void add() {
		try {
			semaphore.acquire();
			Thread.sleep(100);
			count++;
		} catch(InterruptedException e) {
			e.printStackTrace();
		} finally {
			semaphore.release();
		}
	}
	
}

 

除了能实现互斥锁,信号量还可以做到允许多个线程访问同一个临界区,这是它与互斥锁一个较大的区别点。

将代码进行修改,实现限流功能:

package constxiong.interview;

import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 测试使用信号量实现限流的效果
 * @author ConstXiong
 * @date 2019-12-18 14:18:47
 */
public class TestSemaphore {
	
	private static AtomicInteger acount = new AtomicInteger(0);
	
	private static Semaphore semaphore = new Semaphore(10); 
	
	public static void main(String[] args) {
		testAddAtomic();
	}
	
	/**
	 * 测试允许十个线程并发递增 acount
	 */
	private static void testAddAtomic() {
		for (int i = 0; i < 100; i++) {
			new Thread(() -> {
				System.out.println(addAtomic());
			}).start();
		}
	}
	
	private static int addAtomic() {
		try {
			semaphore.acquire();
			Thread.sleep(100);
			return acount.incrementAndGet();
		} catch(InterruptedException e) {
			e.printStackTrace();
		} finally {
			semaphore.release();
		}
		return -1;
	}
	
}

 

在实际的 Java 开发中,信号量的使用相对互斥锁来说较少,知名度没那么高,但在其他编程语言中使用较广。

 

ConstXiong 备案号:苏ICP备16009629号-3