Java的重入锁定和死锁
有人可以向我解释使用Java代码(伪)例子时Reentrant lock
和deadlock
是如何相互关联的?
一个可重入的锁定机构允许持有锁的线重新进入关键部分。 这意味着你可以做这样的事情:
public synchronized void functionOne() {
// do something
functionTwo();
// do something else
// redundant, but permitted...
synchronized(this) {
// do more stuff
}
}
public synchronized void functionTwo() {
// do even more stuff!
}
在非重入锁中,当您尝试从functionOne()
调用functionTwo()
时,会产生死锁情况,因为线程将不得不等待它保存的锁。
当然,死锁是邪恶的情况,线程1持有锁A并等待锁B,而线程2持有锁B并等待锁A.因此,两者都不能继续。 此代码示例创建一个死锁:
public synchronized void deadlock() throws InterruptedException {
Thread th = new Thread() {
public void run() {
deadlock();
}
}.start();
th.join();
}
调用线程会尝试等待生成的线程,而该线程在调用方退出之前不会调用deadlock()
。 嘉潮!
一个线程等待一个永远不会发生的情况,就会发生死锁。
显而易见的情况是,当您尝试锁定两个锁时,由不同线程以不同顺序锁定。
ReentrantLock lock1 = new ReentrantLock();
ReentrantLock lock2 = new ReentrantLock();
public void methodA() {
lock1.lock();
lock2.lock();
// do something and un lock both.
}
public void methodB() {
lock2.lock();
lock1.lock();
// do something and un lock both.
}
正如你所看到的,一个线程可能调用methodA并获得lock1等待lock2,另一个线程调用methodB并获得lock2等待lock1。
但是,线程可能会自行死锁。 一个示例是ReentrantReadWriteLock,因为它不支持将读锁升级到写锁。
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
rwl.readLock().lock();
// do we need to update?
rwl.writeLock().lock(); // will wait for the readLock() to be released!
当隐含的锁正在使用时,自己陷入僵局的尴尬机会。 静态初始化程序块隐式地是线程安全的,因此即使静态初始化程序块未synchronized
也会使用锁定
class A {
private static int VALUE;
static {
Thread t = new Thread() {
public void run() {
// waits for the A class to load.
VALUE = someLongTask();
}
};
t.start();
// waits for the thread.
t.join();
}
}
你再次陷入僵局!
这里有一个ReentrantLock死锁的例子
class Deadlock {
private static final ReentrantLock l1 = new ReentrantLock();
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("A Trying to lock...");
l1.lock();
System.out.println("A Locked...");
try {
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("B Trying to lock...");
l1.lock();
System.out.println("B Must not print");
try {
} finally {
System.out.println("B Trying to unlock...");
l1.unlock();
System.out.println("B Unlocked...");
}
}
});
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
System.out.println("A Trying to unlock...");
l1.unlock();
System.out.println("A Unlocked...");
}
}
});
t.start();
}
}
为了解决死锁问题,请注释掉t.join
,并附上try / catch。