初始化时死锁

时间:2017-05-13 10:33:32

标签: java multithreading

为什么这会在启动时立即陷入死锁 - 它会打印一行然后冻结(在建议的编辑之后)?
这可能是因为firstthread在开始等待之前错过了notify触发器 决议是什么?

public class threadTwo{
    AtomicInteger i=new AtomicInteger(0);
    Boolean b=new Boolean(false);

    class firstThread implements Runnable{
        AtomicInteger i;
        Boolean b;
        firstThread(AtomicInteger i,Boolean b){
            this.i=i;
            this.b=b;
        }
        public void run(){
            while(true){
                synchronized(i){
                    try{
                        while(b==false)
                            i.wait();

                        if(i.intValue()<30){
                            i.incrementAndGet();
                            System.out.println( Thread.currentThread().getId() + " - " + i.intValue());
                        }
                        b=false;
                        i.notify();

                    }catch(InterruptedException x){}
                }
            }
        }       
    }

    class secondThread implements Runnable{
        AtomicInteger i;
        Boolean b;
        secondThread(AtomicInteger i,Boolean b){
            this.i=i;
            this.b=b;
        }
        public void run(){
            while(true){
                synchronized(i){
                    try{
                        while(b==true)
                                i.wait();

                        if(i.intValue()<40){
                            i.getAndAdd(2);
                            System.out.println( Thread.currentThread().getId() + " - " + i.intValue());
                        }
                        b=true;
                        i.notify();

                    }catch(InterruptedException x){}
                }
            }
        }       
    }

    void runThread(){ 
        Thread t1 = new Thread(new firstThread(i,b));
        Thread t2 = new Thread(new secondThread(i,b));
        t1.start();
        t2.start();
        try{
            t1.join();
            t2.join();
        }catch(Exception e){}
        System.out.println("Result : " + i.intValue());
    }

    public static void main(String[] args){
        new threadTwo().runThread();

    }

}

2 个答案:

答案 0 :(得分:2)

b.wait()中的问题为firstThread。 永远不会从b通知此变量secondThread,因为secondThread在支票if(b==true)上失败并立即返回。

但也要注意这样一个事实,即通过变量b的同步是非常糟糕的,因为语句 b=false;b=true;正在为变量分配新实例,因此firstThreadsecondThread会失去连接。

答案 1 :(得分:0)

如果我猜错了代码的意图,那就是不必要的同步和wait-notify。试试这个:

public class MyThread
{
    AtomicInteger i = new AtomicInteger(0);
    Boolean b = new Boolean(false);

    class FirstThread implements Runnable
    {
        AtomicInteger i;
        Boolean b;

        FirstThread(AtomicInteger i, Boolean b)
        {
            this.i = i;
            this.b = b;
        }

        public void run()
        {
            while (i.intValue() < 30)
            {
                i.incrementAndGet();
                System.out.println(Thread.currentThread().getId() + " - " + i.intValue());
            }
        }
    }

    class SecondThread implements Runnable
    {
        AtomicInteger i;
        Boolean b;

        SecondThread(AtomicInteger i, Boolean b)
        {
            this.i = i;
            this.b = b;
        }

        public void run()
        {
            while (i.intValue() < 40)
            {
                i.getAndAdd(2);
                System.out.println(Thread.currentThread().getId() + " - " + i.intValue());
            }
        }
    }

    void runThread()
    {
        Thread t1 = new Thread(new FirstThread(i, b));
        Thread t2 = new Thread(new SecondThread(i, b));
        t1.start();
        try
        {
            t1.join();
        }
        catch (InterruptedException exc)
        {
            exc.printStackTrace();
        }
        t2.start();
        try
        {
            t2.join();
        }
        catch (InterruptedException exc)
        {
            exc.printStackTrace();
        }
        System.out.println("Result : " + i.intValue());
    }

    public static void main(String[] args)
    {
        new MyThread().runThread();

    }
}