Java多线程深入理解学习笔记之五-----锁之不可重入锁和可重入锁

不可重入锁

先来设计一种锁,这一种锁其实是不可重入锁

package 可重入锁和不可重入锁;

public class LockDemo {
	private boolean isLock = false;
	
	
	public synchronized void lock() {
		if(isLock){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		isLock = true;
	}
	
	public synchronized void unLock() {
		isLock = false;
		notify();
	}
	
}
package 可重入锁和不可重入锁;

public class TextDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Demo demo = new Demo();
		demo.printf();
	}

}
package 可重入锁和不可重入锁;

public class Demo {	
	LockDemo lock = new LockDemo();
	public  void printf() {
		lock.lock();
		System.out.println("炒饭");
		addSomeThing();
		lock.unLock();
	}
	
	public  void addSomeThing() {
		lock.lock();
		System.out.println("突然加入某些东西");
		lock.unLock();
	}
}

当调用print()方法时,获得了锁,这时就无法再调用doAdd()方法,这时必须先释放锁才能调用,所以称这种锁为不可重入锁,也叫自旋锁。(如上方法出现了死锁问题)

可重入锁

设计如下:

public class Lock{
    boolean isLocked = false;
    Thread  lockedBy = null;
    int lockedCount = 0;
    public synchronized void lock()
            throws InterruptedException{
        Thread thread = Thread.currentThread();
        while(isLocked && lockedBy != thread){
            wait();
        }
        isLocked = true;
        lockedCount++;
        lockedBy = thread;
    }
    public synchronized void unlock(){
        if(Thread.currentThread() == this.lockedBy){
            lockedCount--;
            if(lockedCount == 0){
                isLocked = false;
                notify();
            }
        }
    }

相对来说,可重入就意味着:线程可以进入任何一个它已经拥有的锁所同步着的代码块。

第一个线程执行print()方法,得到了锁,使lockedBy等于当前线程,也就是说,执行的这个方法的线程获得了这个锁,执行addSomeThing()方法时,同样要先获得锁,因不满足while循环的条件,也就是不等待,继续进行,将此时的lockedCount变量,也就是当前获得锁的数量加一,当释放了所有的锁,才执行notify()。如果在执行这个方法时,有第二个线程想要执行这个方法,因为lockedBy不等于第二个线程,导致这个线程进入了循环,也就是等待,不断执行wait()方法。只有当第一个线程释放了所有的锁,执行了notify()方法,第二个线程才得以跳出循环,继续执行。

这就是可重入锁的特点。

参考博客

猜你喜欢

转载自blog.csdn.net/acDream_/article/details/81516320