使用Semaphore和gets(int)的Java代码中的死锁

Vla*_*lad 12 java multithreading deadlock semaphore

我有以下Java代码:

import java.util.concurrent.*;

class Foo{
    static Semaphore s = new Semaphore(1);

    public void fun(final char c, final int r){
        new Thread(new Runnable(){
            public void run(){
                try{ 
                    s.acquire(r);
                    System.out.println(c+"_"+r);
                    s.release(r+1);
                } catch(Exception e){ e.printStackTrace(); }
            }
        }).start();
    }
}

class ths{
    public static void main(String[]args) throws Exception{
        Foo f = new Foo();
        f.fun('B',2);
        f.fun('F',6);
        f.fun('A',1);
        f.fun('C',3);
        f.fun('D',4);
        f.fun('E',5);
    }
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,这应按顺序打印A_1到F_6并退出,但由于某种原因不会发生.它通常打印A_1和B_2然后卡住.

我的代码找不到任何明显的错误.有什么建议?

NPE*_*NPE 8

基本问题是acquire(int permits)不能保证一次性获取所有许可证.它可以获得更少的许可,然后在等待其余的时候阻止.

我们考虑你的代码.例如,当有三个许可证可用时,没有任何东西可以保证它们会被提供给线程C.事实上,它们可以被赋予线程D以部分满足其acquire(4)请求,从而导致死锁.

如果您更改代码,这可以解决我的问题:

public void fun(final char c, final int r){
    new Thread(new Runnable(){
        public void run(){
            try{ 
                while (!s.tryAcquire(r, 1, TimeUnit.MILLISECONDS)) {};
                System.out.println(c+"_"+r);
                s.release(r+1);
            } catch(Exception e){ e.printStackTrace(); }
        }
    }).start();
}
Run Code Online (Sandbox Code Playgroud)

(在第二个想法,上面也被打破,因为不能保证正确的线程将获得许可 - 它可以继续尝试并无限期地超时.)