Java 信号量函数中的死锁

Java 信号量函数中的死锁,java,multithreading,Java,Multithreading,问题1: 我在阅读时遇到了下面的信号量示例 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

问题1:

我在阅读时遇到了下面的信号量示例

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();
    }
}
package com.dswgroup.conferences.borcon.threading;
公共类资源管理器{
私人整数计数;
私人int max;
公共资源管理器(int max){
计数=0;
this.max=max;
}
公共同步的void getResource(int numberof){
while(true){
如果((计数+数字)
所有资源都在使用中,一个新线程请求不可用的资源。由于它在同步函数内等待,使用这些资源的其他线程无法释放资源,因为freeResource函数也在同步中,并且由于等待的线程已执行oResourceGovernor的对象级别锁

您没有注意到调用
wait()
会放弃监视器,因此可以执行其他同步代码。来自以下文档:

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

关于第二个问题:

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

我怀疑是这样,尽管您所展示的实现实际上并没有阻止您多次调用
freereresource
。这是一个有点奇怪的实现,因为我通常看到信号量计算剩余资源的数量,而不是占用的资源的数量——当然,它们是等效的

所有资源都在使用中,一个新线程请求不可用的资源。由于它在同步函数内等待,使用这些资源的其他线程无法释放资源,因为freeResource函数也在同步中,并且由于等待的线程已执行oResourceGovernor的对象级别锁

您没有注意到调用
wait()
会放弃监视器,因此可以执行其他同步代码。来自以下文档:

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

关于第二个问题:

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


我想是这样的,尽管您所展示的实现实际上并没有阻止您多次调用
freeResource
。这是一个有点奇怪的实现,因为我通常看到信号量计算剩余资源的数量,而不是占用的资源的数量——当然,它们是等效的。

问题2:是的,它类似于互斥。但是,尽管互斥和信号量在其实现中有相似之处,但它们的使用应该总是不同的。

问题2:是的,它类似于互斥。但是,尽管互斥和信号量在其实现中有相似之处,但它们的使用应该总是不同的。

您给我的验证问题ntioned可能是故意的。例如,JDK的信号灯类声明“不要求发布许可证的线程必须通过调用acquire来获取该许可证。”创建没有许可证的信号灯,让一个线程尝试获取许可证,然后让另一个线程“释放”许可证是完全合法的这样,信号量也可以模拟倒计时锁存器(类似于二进制信号量-1-permit-可以模拟互斥锁存器的方式)。请记住,这篇文章是2004年的。它的所有内容今天都被弃用。要获得更好的解决方案,请查看并发包。您提到的验证问题可能是有意为之。例如,JDK的信号量类声明“不要求发布许可证的线程必须通过调用acquire获得该许可证。”完全可以在没有许可证的情况下创建信号量,让一个线程尝试获取许可证,然后让另一个线程“发布”许可证(一开始从未获得过许可证)。通过这种方式,信号量也可以模拟倒计时锁存器(类似于二进制信号量-1许可证-可以模拟互斥)。请记住,这篇文章是从2004年开始的。它的所有内容今天都被弃用。要获得更好的解决方案,请查看并发包。