Semaphore 源码

package cn.semaphore.n1;

import java.util.concurrent.Semaphore;

public class Pool {
	private static final int MAX_AVAILABLE=2;
	private final Semaphore available=new Semaphore(MAX_AVAILABLE, true);
	private Connection[] items=new Connection[MAX_AVAILABLE];
	public Pool(){
		for(int i=0;i<MAX_AVAILABLE;i++){
			items[i]=new Connection(i+1);
		}
	}
	
	private boolean[] used=new boolean[MAX_AVAILABLE];
	
	
	public Connection getItem() throws InterruptedException{
		available.acquire();
		return getNextAvailableItem();
	}
	
	public boolean putItem(Connection x){
		if(markAsUnused(x)){
			available.release();
			return true;
		}else{
			return false;
		}
	}
	
	private synchronized Connection getNextAvailableItem(){
		for(int i=0;i<MAX_AVAILABLE;i++){
			if(!used[i]){
				used[i]=true;
				return items[i];
			}
		}
		return null;
	}
	
	private synchronized boolean markAsUnused(Connection x){
		for(int i=0;i<MAX_AVAILABLE;i++){
			if(x.getId()==items[i].getId()){
				if(used[i]){
					used[i]=false;
					return true;
				}else{
					return false;
				}
			}
		}
		return false;
	}
}
package cn.semaphore.n1;

public class Connection {
	private int id;
	public Connection(int i){
		id=i;
	}
	public String toString() {
		return "Connection [id=" + id + "]";
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
}
package cn.semaphore.n1;

import java.util.Random;

public class St1 {

	public static void main(String[] args) {
		final Pool pool = new Pool();
		final Random random = new Random();
		for(int i=0;i<12;i++){
			new Thread(new Runnable() {
				
				public void run() {
					
					int nextInt = random.nextInt(3000);
					
					try {
						Thread.sleep(nextInt);
						Connection item = pool.getItem();
						System.out.println(Thread.currentThread().getName()+" 获取连接"+item);
						Thread.sleep(3000);
						System.out.println(Thread.currentThread().getName()+" 释放连接"+item+" "+pool.putItem(item));
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
				}
			}).start();
		}

	}

}

这是信号量的一个简单应用,获取连接前先获取许可,释放连接后要释放许可。

输出:

Thread-7 获取连接Connection [id=1]
Thread-5 获取连接Connection [id=2]
Thread-7 释放连接Connection [id=1] true
Thread-9 获取连接Connection [id=1]
Thread-5 释放连接Connection [id=2] true
Thread-4 获取连接Connection [id=2]
Thread-9 释放连接Connection [id=1] true
Thread-6 获取连接Connection [id=1]
Thread-4 释放连接Connection [id=2] true
Thread-1 获取连接Connection [id=2]
Thread-6 释放连接Connection [id=1] true
Thread-11 获取连接Connection [id=1]
Thread-1 释放连接Connection [id=2] true
Thread-0 获取连接Connection [id=2]
Thread-11 释放连接Connection [id=1] true
Thread-2 获取连接Connection [id=1]
Thread-0 释放连接Connection [id=2] true
Thread-3 获取连接Connection [id=2]
Thread-2 释放连接Connection [id=1] true
Thread-8 获取连接Connection [id=1]
Thread-3 释放连接Connection [id=2] true
Thread-10 获取连接Connection [id=2]
Thread-8 释放连接Connection [id=1] true
Thread-10 释放连接Connection [id=2] true
 

源码:

Semaphore(int permits) 初始化资源数,默认使用非公平锁,第二个参数设置为true公平锁。

acquire 获取资源,使用AQS共享模式获取资源。
非公平锁 tryAcquireShared:aqs共享模式尝试获取资源:自旋 获取aqs资源数,对资源数-1,如果剩余资源数小于0或者cas修改资源数为剩余资源数成功,则返回,否则自旋。
公平锁 tryAcquireShared:自旋 如果线程等待队列有节点等待获取资源,失败返回-1,否则 获取资源数,对资源数-1,如果剩余资源数小于0或者cas修改资源数成功,则返回 否则自旋。

release 释放资源,使用AQS共享模式释放资源。
tryReleaseShared aqs共享模式 尝试释放资源:自旋 获取资源数,cas操作对资源数+1,成功返回true,失败自旋。

猜你喜欢

转载自blog.csdn.net/liangwenmail/article/details/81487652