编写你自己的Mutex类

我们知道,在JAVA中用关键字synchronized控制对临界区的互斥访问,以此保障线程安全性,有synchronized方法和synchronized块。

如果是成对的lock(),unlock()方法,也可以达到同样的效果,如下面代码:

	void method()
	{
		mutex.lock();
		try
		{
			//critical section
			do something;
		}
		finally
		{
			mutex.unlock();
		}
	}

这种finally的使用方法,是Before/After Pattern(事前/事后 Pattern)的一种实现方式。

那我们如何编写自己的Mutex类,保障线程的安全性呢?


一、单纯的Mutex 类

添加一字段标识是否已加锁。

public final class Mutex{
	
	private boolean busy = false;
	
	public synchronized void lock()
	{
		while(busy)
		{
			try{
				//if the lock has been occupied, suspend the current thread
				wait();
			}
			catch(InterruptedException e){}
		}
		
		//hold the lock
		busy = true;
	}
	
	public synchronized void unlock()
	{
		//release the lock
		busy = false;
		//notify all of the waiting threads
		notifyAll();
	}
}

该Mutex类在上边method的情况会正确的运行,但在其它情况下,如Mutex类的重复使用就会有问题,这也是对其使用的限制:

问题1:假设有某个线程连续两次调用 lock方法,在第2次调用时,由于busy字段已经变成true,因此会wait,线程挂起,这就如同将自己锁在外边,进不了门一样。

问题2:即使是尚未调用lock()方法的线程,也可以调用unlock()方法。就如同即使不是自己上的锁,自己还是可以将门打开一样。


二、改良的Mutex类

 针对上述问题,使用字段 locks、owner解决重复加锁,并在unlock() 中处理未加锁便解锁的情况。

public final class Mutex{

	private long locks = 0;		//number of locks
	private Thread owner = null;	//the owner who holds the lock
	
	public synchronized void lock()
	{
		Thread me = Thread.currentThread();
		while(locks > 0 && owner != me)
		{
			try{
				wait();
			}
			catch(InterruptedException e){}
		}
		//locks == 0 || owner = me
		owner = me;
		locks ++;
	}
	
	public synchronized void unlock()
	{
		Thread me = Thread.currentThread();
		//never happens
		assert(locks == 0 || owner != me);
		
		//locks > 0 && owner == me
		locks--;
		if(locks == 0)
		{
			owner = null;
			notifyAll();
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值