有人可以向我解释Reentrant lock
和deadlock
与Java代码(伪)例子的相互关系吗?Java中的可重入锁定和死锁
7
A
回答
11
一个可重入的锁定机制允许持有锁的线程重新进入关键部分。这意味着你可以做这样的事情:
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!
}
在非重入锁,你将有一个死锁的情况,当你尝试调用functionTwo()
从functionOne()
因为线程必须等待锁..它自己拥有。
死锁当然是线程1持有锁A并等待锁B而线程2持有锁B并等待锁A的恶劣情况。因此,两者都不能继续。此代码示例创建了一个僵局:
public synchronized void deadlock() throws InterruptedException {
Thread th = new Thread() {
public void run() {
deadlock();
}
}.start();
th.join();
}
调用线程试图等待各地的产生的线程,这又不能打电话deadlock()
直到呼叫方已退出。嘉潮!
0
即使通过输入其他代码块已经获得锁定,可重入锁定仍将允许锁定持有者输入代码块。一个不可重入的锁会让锁持有者自己锁定,因为它必须释放从另一个代码块获得的锁以重新获得同一个锁以进入需要代码块的嵌套锁。就死锁而言,如果您从受保护的代码块中调用受保护的代码块,您将需要一个可重入的锁(或者在等待自己时您会死锁)。
1
这里的僵局与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一起。
6
死锁发生,然后线程等待一个永远不会发生的情况。
显而易见的情况是,当您试图锁定两个锁时,按不同的线程以不同的顺序锁定。
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并获得锁1等待锁2,和另一个线程调用的methodB并获得锁2等待锁1。
但是,它可能导致线程自身死锁。一个示例是ReentrantReadWriteLock,因为它不支持将读锁升级到写锁。
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
rwl.readLock().lock();
// do we need to update?
rwl.writeLock().lock(); // will wait for the readLock() to be released!
一个不起眼的机会死锁自己是在暗示锁使用。所以锁用于即使静态初始化器块不
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();
}
}
同样,你有一个僵局静态初始化器块隐含线程安全的!
相关问题
- 1. 正确的锁定/解锁使用Java的可重入锁
- 2. 可重入锁定
- 3. Java ExecuterService死锁?
- 4. Python线程和锁定:死锁
- 5. Postgresql锁死锁
- 6. 可重入锁定问题
- 7. pthread_mutex_timedlock和死锁
- 8. Quartz.NET和死锁
- 9. Restkit和死锁
- 10. Java,线程死锁?
- 11. Java死锁问题
- 12. Java线程死锁
- 13. ActiveRecord3死锁重试
- 14. 在SQL中使用双重检查锁定的死锁
- 15. MySQL返回死锁插入行和FK被锁定'更新'
- 16. 带锁的单身人士 - 可能的死锁?在java
- 17. 锁分区死锁
- 18. 死锁锁()方法
- 19. java中的LinkedBlockingQueue和写入锁定
- 20. MS SQL Server中的IsolationLevel,锁定模式,死锁和sp_getapplock
- 21. Java:奇怪的死锁
- 22. 死锁的线程java
- 23. Java的新手 - 死锁仿
- 24. 带锁的死锁工作
- 25. 强制解锁一个可重入锁
- 26. 了TerminateProcess和死锁
- 27. 死锁SQLServer中
- 28. Java的:为什么这是一个死锁时锁定为空?
- 29. 死锁
- 30. TAO在锁定时发生死锁
我猜OP意味着使用类java.util.concurrent.locks.ReentrantLock而不是'synchronized'块的例子。 –
@Victor Sorokin我不确定他是否适合大写字母。不管是使用'synchronized'块还是'ReentrantLock'类,高级概念都是完全相同的。 – stevevls