问答详情
源自:5-1 总结及展望

多线程唤醒问题

public class FlagWork {
    public static void main(String[] args) {
        final Business1 b1 = new Business1();
        new Thread(new Runnable() {
 
            @Override
            public void run() {
                b1.a();
            }
        }).start();
        new Thread(new Runnable() {
 
            @Override
            public void run() {
                b1.b();
            }
        }).start();
        new Thread(new Runnable() {
             
            @Override
            public void run() {
                b1.c();
            }
        }).start();
    }
}
 
class Business1 {
    private int flag = 1;
 
    public void a() {
        for (int i = 0; i < 50; i++) {
            synchronized (this) {
                while (flag != 1) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                for (int j = 1; j <= 10; j++) {
                    System.out.println("线程a运行" + j + "次");
                }
                flag = 2;
                this.notify();
            }
        }
    }
 
    public void b() {
        for (int i = 0; i < 50; i++) {
            synchronized (this) {
                while (flag != 2) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                for (int j = 1; j <= 20; j++) {
                    System.out.println("线程b运行" + j + "次");
                }
                flag = 3;
                this.notify();
            }
        }
    }
    public void c() {
        for (int i = 0; i < 50; i++) {
            synchronized(this){
                while(flag!=3){
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                for (int j = 1; j <= 30; j++) {
                    System.out.println("线程c运行"+j+"次");
                }
                flag = 1;
                this.notifyAll();
            }
        }
    }
}

A线程先运行10次,然后B线程运行20次,然后C线程运行30次,如此反复50次的代码,为什么次c方法里要用this.notifyAll,而用this.notify就不行

提问者:_Everglow 2017-02-09 14:31

个回答

  • 乱星海
    2017-02-09 20:21:52
    已采纳

    三个方法里至少有一个是notifyAll。假设三个都是notify(),当方法c运行完后,flag为1,此时如果a和b都已经在Wait Set中,且随机唤醒的是b,那么b随机又进入Wait set,c也进入Wait set,此时三个线程全部进入Wait set,造成了死锁。

  • gzkahjl
    2020-12-13 20:55:43

    哈哈  确实??