Java 使用ReentrantLock避免死锁
我在做一些练习作业,并尝试使用一些虚拟代码来更好地理解线程和锁的概念。下面是一段(有时)陷入死锁的代码 A.java B.java Demo.java 解决方案:我使用了Java 使用ReentrantLock避免死锁,java,multithreading,thread-safety,locking,Java,Multithreading,Thread Safety,Locking,我在做一些练习作业,并尝试使用一些虚拟代码来更好地理解线程和锁的概念。下面是一段(有时)陷入死锁的代码 A.java B.java Demo.java 解决方案:我使用了锁s而不是同步 A.java B.java 进行上述更改后,代码不会导致死锁。这是实现这一点的正确方法吗(基本上,我希望查看impendingExecute()方法)?另外,(有点偏离评论)有没有我能遇到的真实场景 注意:我已经在代码审查上发布了这个问题,但似乎虚拟代码的审查是离题的。您可以使用java.util.concurr
锁
s而不是同步
A.java
B.java
进行上述更改后,代码不会导致死锁。这是实现这一点的正确方法吗(基本上,我希望查看impendingExecute()
方法)?另外,(有点偏离评论)有没有我能遇到的真实场景
注意:我已经在代码审查上发布了这个问题,但似乎虚拟代码的审查是离题的。您可以使用
java.util.concurrent.locks.ReentrantLock
。这种设计允许该方法尝试获取这两个类的锁,如果失败则释放锁,必要时稍后重试。如果您需要尝试直到成功,那么您需要将它放入一个循环中,并以某种策略终止
while (true) {
if (this.lock.tryLock()) {
try {
if (ba.lock.tryLock()) {
try {
//some logic
break;
} finally {
ba.lock.unlock();
}
}
} finally {
this.lock.unlock();
}
}
int n = number.nextInt(1000);
int TIME = 1000 + n; // 1 second + random delay to prevent livelock
Thread.sleep(TIME);
}
或者,您可以使用此解决方案,确保以相同的顺序获取和释放多个锁:
if (compareTo(ba) < 0) {
former = this;
latter = ba;
} else {
former = ba;
latter = this;
}
synchronized (former) {
synchronized (latter) {
//Some logic
}
}
}
if(与(ba)<0相比){
前者=此;
后者=ba;
}否则{
前者=ba;
后者=这个;
}
同步(前){
同步(后者){
//一些逻辑
}
}
}
感谢您的及时回复:)
public class Demo {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
new Thread(() -> {
a.foo(true);
}).start();
new Thread(() -> {
b.bar(true);
}).start();
}
}
public class A {
private final ReentrantLock lock = new ReentrantLock();
private B b;
public void setB(B b) {
this.b = b;
}
public ReentrantLock lock() {
return lock;
}
public boolean impendingExecute() {
Boolean thisLock = false;
Boolean otherLock = false;
try {
thisLock = lock.tryLock();
otherLock = b.lock().tryLock();
} finally {
if (!(thisLock && otherLock)) {
if (thisLock) {
lock.unlock();
}
if (otherLock) {
b.lock().unlock();
}
}
}
return thisLock && otherLock;
}
public void foo(boolean callBar) {
System.out.println("foo");
if (callBar && impendingExecute()) {
try {
b.bar(false);
} finally {
lock.unlock();
b.lock().unlock();
}
}
}
}
public class B {
private final ReentrantLock lock = new ReentrantLock();
private A a;
public void setA(A a) {
this.a = a;
}
public ReentrantLock lock() {
return lock;
}
public boolean impendingExecute() {
Boolean thisLock = false;
Boolean otherLock = false;
try {
thisLock = lock.tryLock();
otherLock = a.lock().tryLock();
} finally {
if (!(thisLock && otherLock)) {
if (thisLock) {
lock.unlock();
}
if (otherLock) {
a.lock().unlock();
}
}
}
return thisLock && otherLock;
}
public void bar(boolean callFoo) {
System.out.println("bar");
if (callFoo && impendingExecute()) {
try {
a.foo(false);
} finally {
lock.unlock();
a.lock().unlock();
}
}
}
}
while (true) {
if (this.lock.tryLock()) {
try {
if (ba.lock.tryLock()) {
try {
//some logic
break;
} finally {
ba.lock.unlock();
}
}
} finally {
this.lock.unlock();
}
}
int n = number.nextInt(1000);
int TIME = 1000 + n; // 1 second + random delay to prevent livelock
Thread.sleep(TIME);
}
if (compareTo(ba) < 0) {
former = this;
latter = ba;
} else {
former = ba;
latter = this;
}
synchronized (former) {
synchronized (latter) {
//Some logic
}
}
}