可重入锁vs不可重入锁

2019-06-16  本文已影响0人  归来依旧少女

一、代码展示

先设计一个不可重入锁:

public class UnreentrantLock {

private Thread localThread;

private boolean isLocked = false;

/**

* 加锁

* @throws InterruptedException

*/

public synchronized void lock() throws InterruptedException {

while(isLocked) {

System.out.println(Thread.currentThread().getName()+"没有获取到锁,等待中");

wait();

}

isLocked = true;

localThread = Thread.currentThread();

System.out.println(localThread.getName()+"获取到锁");

}

/**

* 解锁

*/

public void unlock() {

if(isLocked) {

System.out.println(Thread.currentThread().getName()+"释放锁");

isLocked = false;

localThread = null;

}

}

}



测试:

public class Count {

private UnreentrantLock lock = new UnreentrantLock();

public void print() {

try {

lock.lock();

System.out.println("print start..");

//调用add()方法

add();

lock.unlock();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public void add() {

try {

lock.lock();

System.out.println("add...");

lock.unlock();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

Count count = new Count();

count.print();

}

}

运行结果:

main获取到锁

print start..

main没有获取到锁,等待中

可以看到同一个线程,重复获取锁失败,形成死锁,这就是不可重入锁。

然后再写一个可重入锁:

public class ReentrantLock {

private Thread localThread = null;

private boolean isLocked = false;

private int lockedCount = 0;

/**

* 加锁

*

* @throws InterruptedException

*/

public synchronized void lock() throws InterruptedException {

Thread thread = Thread.currentThread();

while (isLocked && localThread != thread) {

System.out.println(Thread.currentThread().getName() + "没有获取到锁,等待中");

wait();

}

isLocked = true;

localThread = thread;

lockedCount++;

System.out.println(localThread.getName() + "获取到锁");

}

/**

* 解锁

*/

public void unlock() {

if (isLocked) {

System.out.println(Thread.currentThread().getName() + "释放锁");

lockedCount--;

if (lockedCount == 0) {

isLocked = false;

localThread = null;

}

}

}

}

测试:

private ReentrantLock lock = new ReentrantLock();

运行结果:

    main获取到锁

    print start..

    main获取到锁

    add...

    main释放锁

    main释放锁

可以看到,同一个线程可以多次获取锁。

二、总结

可重入锁又称之为递归锁,就是一个线程在外层方法获取到锁,在内层方法自动获取到锁,而不会因为没有获取到锁而阻塞。java中的ReentrantLock和synchronized都是可重入锁。可重入锁可一定程度上减少死锁,而不可重入锁则再容易发生死锁。

上一篇下一篇

猜你喜欢

热点阅读