Java多线程-并发工具类Semaphore详解

Dcr 1年前 ⋅ 1203 阅读

概念

计数信号量,一个初始化为1的信号量,并且它最多只能有一个permit可用,可以作为互斥锁。这通常被称为二进制信号量,因为它只有两种状态:一个可用的许可证,或零可用的许可证。当以这种方式使用时,二进制信号量具有这样的属性(与许多java.util.concurrent.locks.Lock实现不同),即“锁”可以由所有者以外的线程释放(因为信号量没有所有权的概念)。这在某些特定的上下文中可能很有用,比如死锁恢复。 该类的构造函数可选接受一个公平性参数.false时不保证线程获得许可的顺序,true反之;这里需要注意的是不定时的tryAcquire方法不适用公平性设置. 通常,用来控制资源访问的信号量应该被初始化为公平的,以确保没有线程在访问资源时被耗尽。当将信号量用于其他类型的同步控制时,不公平排序的吞吐量优势往往超过公平性考虑。

应用场景

  • 用于多个共享资源的互斥使用.
  • 用于并发线程数的控制.
  • 流量控制

注意事项

  • 同一个信号量可以重复释放,官方给的案例中,需要单独维护该信号量状态
  • release()调用应该放在finally块中,避免出现异常情况下信号量无归还
  • Semaphore默认采用非公平策略

官方例子

class Pool {
	private static final int MAX_AVAILABLE = 100;
	private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
	public Object getItem() throws InterruptedException {       
		available.acquire();       
		return getNextAvailableItem();     
	}

	public void putItem(Object x) {       
	if (markAsUnused(x))         
		available.release();     
	}

	 protected Object[] items = ... whatever kinds of items being managed     
	 protected boolean[] used = new boolean[MAX_AVAILABLE];


	protected synchronized Object getNextAvailableItem() {       
		for (int i = 0; i < MAX_AVAILABLE; ++i) {         
			if (!used[i]) {            
				used[i] = true;            
				return items[i];         
			}       
		}       
		return null; // not reached     
	}

	protected synchronized boolean markAsUnused(Object item) {       
		for (int i = 0; i < MAX_AVAILABLE; ++i) {         
			if (item == items[i]) {            
				if (used[i]) {              
					used[i] = false;              
					return true;            
			} else {             
			return false;         
			}       
		}       
		return false;     
	}

}

全部评论: 0

    我有话说: