首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用ReentrantLock避免死锁

使用ReentrantLock避免死锁
EN

Stack Overflow用户
提问于 2017-05-21 08:05:43
回答 1查看 1.2K关注 0票数 1

我正在做一些实践作业,并尝试使用一些虚拟代码,以便更好地理解线程和锁的概念。下面是一段(有时)陷入死锁的代码。

A.java

代码语言:javascript
复制
public class A {

    private B b;

    public void setB(B b) {
        this.b = b;
    }

    public synchronized void foo(boolean callBar) {
        System.out.println("foo");
        if (callBar) {
            b.bar(false);
        }
    }
}

B.java

代码语言:javascript
复制
public class B {

    private A a;

    public void setA(A a) {
        this.a = a;
    }

    public synchronized void bar(boolean callFoo) {
        System.out.println("bar");
        if (callFoo) {
            a.foo(false);
        }
    }
}

Demo.java

代码语言:javascript
复制
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();
    }
}

解决方案:我使用Lock而不是synchronized

A.java

代码语言:javascript
复制
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();
            }
        }
    }
}

B.java

代码语言:javascript
复制
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();
            }
        }
    }
}

在进行上述更改后,代码不会导致死锁。这是实现这个方法的正确方法吗(基本上,我希望对impendingExecute()方法进行审查。)此外,(有点偏离审查)是否有任何现实世界的场景,我可以遇到这种情况?

注意:我在“代码评论”上发布了这个问题,但似乎对虚拟代码的评论已经过时了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-05-21 08:21:09

您可以使用java.util.concurrent.locks.ReentrantLock。此设计允许该方法尝试获取两个类的锁,如果失败则释放锁,并在必要时再试一次。如果您需要尝试直到成功,那么您需要在循环中放置一个it并使用一些策略终止。

代码语言:javascript
复制
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);
}

或者您可以使用此解决方案来确保以相同的顺序获取和释放多个锁:

代码语言:javascript
复制
if (compareTo(ba) < 0) {
        former = this;
        latter = ba;
    } else {
        former = ba;
        latter = this;
    }
    synchronized (former) {
        synchronized (latter) {
            //Some logic
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44094584

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档