信号量函数中的死锁

时间:2013-12-02 06:51:56

标签: java multithreading

问题1:

我正在阅读Hard-core Multi-threading in Java并且确实碰到了下面的信号量示例。

package com.dswgroup.conferences.borcon.threading;

public class ResourceGovernor {
    private int count;
    private int max;

    public ResourceGovernor(int max) {
        count = 0;
        this.max = max;
    }

    public synchronized void getResource(int numberof) {
        while (true) {
            if ((count + numberof) <= max) {
                count += numberof;
                break;
            }
            try {
                wait();
            } catch (Exception ignored) {}
        }
    }

    public synchronized void freeResource(int numberof) {
        count -= numberof;
        notifyAll();
    }
}

我认为这可能导致以下情况出现僵局:

正在使用所有资源,新线程会询问不可用的资源。 由于它在同步函数内部等待,因此使用资源的其他线程无法释放资源,因为freeResource函数也被同步,并且由于等待线程已采用对象级锁定而无法进入该函数的 ResourceGovernor

还有一个问题是,如果某个线程试图释放更多no,则尚未验证。资源比它获得的资源。但是这个问题是次要的,可以通过使用线程名称和资源计数的同步映射来轻松修复。

但我能否安全地说我正确诊断出第一个问题。 (自embarcadero.com上发布很长时间以来需要进行双重检查)

问题2:

我能否安全地说只有1个资源的信号量与互斥锁具有相同的行为?

2 个答案:

答案 0 :(得分:5)

  

正在使用所有资源,新线程会询问不可用的资源。由于它在同步函数内部等待,因此使用资源的其他线程无法释放资源,因为freeResource函数也被同步,并且由于等待线程已采用对象级锁定而无法进入该函数ResourceGovernor

您错过了调用wait()放弃监视器的事实,因此其他同步代码 能够执行。来自wait()的文档:

  

当前线程必须拥有此对象的监视器。线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象监视器上的线程唤醒。然后该线程等待,直到它可以重新获得监视器的所有权并继续执行。

关于你的第二个问题:

  

我可以安全地说只有1个资源的信号量与互斥锁具有相同的行为吗?

我怀疑是这样,虽然您展示的实施实际上并没有阻止您多次致电freeResource。这是一个有点奇怪的实现,因为我通常会看到信号量计算剩余的资源数量而不是采取的资源数量 - 当然,它们是等效的。

答案 1 :(得分:1)

问题2:是的,它类似于互斥锁。但是,虽然互斥体和信号量在实现上有相似之处,但它们应始终以不同的方式使用。 Nice Explanation Here