Java中的Semaphore信号量机制

什么是信号量机制

信号量机制是一种通过使用计数器来控制共享资源访问的机制,计数器计数的是共享资源的访问许可,如果计数器大于0则允许访问,如果为0,则拒绝访问。Java在java.util.concurrent包中提供了Semaphore类实现该机制。

Semaphore工作流程

通常,在线程想要访问共享资源时,会用到Semaphore获取许可。

  • 如果Semaphore计数大于0,则获得许可,Semaphore计数器减1
  • 否则,线程将被阻塞,直到获得许可。
  • 当线程不再需要访问共享资源时,他会释放许可,此时Semaphore计数器加1。
  • 如果此时有其他线程在等待许可,它将立刻获得许可。

在这里插入图片描述

Semaphore使用方式

Semaphore一共有两个构造函数:

Semaphore(int permits)
Semaphore(int permits, boolean fair)

此处peimits用于指定初始许可数,也就是说它代表了同一时刻可以并发访问共享资源的最大线程数,默认情况下Semaphore使用的是非公平锁,通过将fair参数设置为true可以改用公平锁。

下面例子中,我们使用Semaphore来锁定对资源的访问,每个想要使用该资源的线程必须在访问之前先调用acquire()获取锁,当线程使用完毕后,它必须调用release()来释放锁。

// java program to demonstrate
// use of semaphores Locks
import java.util.concurrent.*;

//A shared resource/class.
class Shared
{
	static int count = 0;
}

class MyThread extends Thread
{
	Semaphore sem;
	String threadName;
	public MyThread(Semaphore sem, String threadName)
	{
		super(threadName);
		this.sem = sem;
		this.threadName = threadName;
	}

	@Override
	public void run() {
		
		// run by thread A
		if(this.getName().equals("A"))
		{
			System.out.println("Starting " + threadName);
			try
			{
				// First, get a permit.
				System.out.println(threadName + " is waiting for a permit.");
			
				// acquiring the lock
				sem.acquire();
			
				System.out.println(threadName + " gets a permit.");
		
				// Now, accessing the shared resource.
				// other waiting threads will wait, until this
				// thread release the lock
				for(int i=0; i < 5; i++)
				{
					Shared.count++;
					System.out.println(threadName + ": " + Shared.count);
		
					// Now, allowing a context switch -- if possible.
					// for thread B to execute
					Thread.sleep(10);
				}
			} catch (InterruptedException exc) {
					System.out.println(exc);
				}
		
				// Release the permit.
				System.out.println(threadName + " releases the permit.");
				sem.release();
		}
		
		// run by thread B
		else
		{
			System.out.println("Starting " + threadName);
			try
			{
				// First, get a permit.
				System.out.println(threadName + " is waiting for a permit.");
			
				// acquiring the lock
				sem.acquire();
			
				System.out.println(threadName + " gets a permit.");
		
				// Now, accessing the shared resource.
				// other waiting threads will wait, until this
				// thread release the lock
				for(int i=0; i < 5; i++)
				{
					Shared.count--;
					System.out.println(threadName + ": " + Shared.count);
		
					// Now, allowing a context switch -- if possible.
					// for thread A to execute
					Thread.sleep(10);
				}
			} catch (InterruptedException exc) {
					System.out.println(exc);
				}
				// Release the permit.
				System.out.println(threadName + " releases the permit.");
				sem.release();
		}
	}
}

// Driver class
public class SemaphoreDemo
{
	public static void main(String args[]) throws InterruptedException
	{
		// creating a Semaphore object
		// with number of permits 1
		Semaphore sem = new Semaphore(1);
		
		// creating two threads with name A and B
		// Note that thread A will increment the count
		// and thread B will decrement the count
		MyThread mt1 = new MyThread(sem, "A");
		MyThread mt2 = new MyThread(sem, "B");
		
		// stating threads A and B
		mt1.start();
		mt2.start();
		
		// waiting for threads A and B
		mt1.join();
		mt2.join();
		
		// count will always remain 0 after
		// both threads will complete their execution
		System.out.println("count: " + Shared.count);
	}
}

Output:

Starting A
Starting B
A is waiting for a permit.
B is waiting for a permit.
A gets a permit.
A: 1
A: 2
A: 3
A: 4
A: 5
A releases the permit.
B gets a permit.
B: 4
B: 3
B: 2
B: 1
B: 0
B releases the permit.
count: 0
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值