40 多线程(十二)——ReentrantLock 可重入锁

我们使用的synchronized加的锁是可以延续使用的,如下:

 public void test() {
	 //第一次获得锁
	 synchronized(this) {
		 while(true) {
			 //第二次获得同样的锁
			 synchronized(this) {
				 System.out.println("ReentrantLock");
			 }
			 try {
				 Thread.sleep(1000);
			 } catch (InterruptedException e) {
				 // TODO Auto-generated catch block
				 e.printStackTrace();
			 }
		 }
	 }
 }

  

使用synchronized加的锁必须等到线程结束才会被释放,这可能会造成死锁。

而相对synchronized,ReentrantLock锁更灵活,它可以指定加锁一段时间后主动释放锁等更为强大的功能,目前仅做了解即可。

详细内容自行百度。接下来仿写ReentrantLock源码,实现基本的lock与unLock方法。

package _20191209;
/**
 * 可重入锁演示:锁不以延续使用
 * @author TEDU
 *
 */
public class LockTest03 {
	ReLock lock = new ReLock();
	public void a() throws InterruptedException {
		lock.lock();
		System.out.println(lock.getHoldCount());
		doSomething();//需要被加锁的部分
		lock.unlock();
		System.out.println(lock.getHoldCount());
 }
	
 public void doSomething() throws InterruptedException {
	 lock.lock();
	 System.out.println(lock.getHoldCount());
	 //。。。。。。
	 lock.unlock();
	 System.out.println(lock.getHoldCount());
 }
 
	public static void main(String[] args) throws InterruptedException {
		LockTest03 test = new LockTest03();
		test.a();
	}
 
}
//可重入锁
class ReLock{
	//是否被占用
	private boolean isLocked = false;
	//存储线程的变量
	private Thread lockedBy = null;
	//锁计数器:锁使用次数
	private int holdCount = 0;
	//使用锁
	public synchronized void lock() throws InterruptedException{
		Thread t = Thread.currentThread();
		while(isLocked && lockedBy != t) {
			wait();
		}
		
		isLocked = true;
		lockedBy = t;
		holdCount ++;
	}
	//释放锁
	public synchronized void unlock() {
		if(Thread.currentThread() == lockedBy) {
			holdCount --;
			if(holdCount == 0) {
				isLocked = false;
				notify();
				lockedBy = null;
			}
		}
	}
	public int getHoldCount() {
		return holdCount;
	}
}

  

如果需要使用ReentrantLock只需要new一个就行了:

ReentrantLock relock = new ReentrantLock();
relock.lock();//加锁
relock.unlock();//解锁

  

 

posted @ 2019-12-09 17:54  Scorpicat  阅读(268)  评论(0编辑  收藏  举报