Java代码 - 线程相互阻塞

时间:2017-07-29 15:02:15

标签: java multithreading

我是多线程的新手。我正在尝试编写一个程序,我有两个线程。一个线程打印奇数,然后使用wait()放弃监视器锁定,同样其他线程打印偶数并在打印数字后放弃锁定 我有4个班级

  1. Odd.java(在1-100之间打印奇数)
  2. Even.java(在1-100之间打印偶数)
  3. SomeMaths.java(有打印奇数和偶数的逻辑)
  4. OEApp.java(启动主题的主类)
  5. 问题 - 我的代码大部分时间都按预期工作,即按顺序打印1到100。两个线程轮流。但是我注意到有一个bug。有时甚至线程会先安排好,然后输出低于输出

    2    **********
    1    ###############################
    

    之后没有任何内容被打印出来,看起来有一个死锁的情况。我无法弄清楚原因。请帮我理解这个

    public class SomeMaths {
    
        public synchronized void printOdd(){
            for( int i=1;i<=100;i++){
                if(i%2 !=0) {
                    System.out.println(i + "       ###############################");
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                notify();
            }
        }
    
        public synchronized void printEven(){
            for(int i=1;i<=100;i++){
                if(i%2 ==0){
                    System.out.println(i +"    **********");
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                notify();
            }
        }
      }
    

    public class Odd implements Runnable {
    
        SomeMaths sm;
    
        public Odd(SomeMaths sm){
            this.sm = sm;
        }
        @Override
        public void run(){
           sm.printOdd();
        }
    }
    

    public class Even extends Thread {
    
        SomeMaths sm;
    
        public Even(SomeMaths sm){
            this.sm = sm;
        }
    
        @Override
        public void run(){
            sm.printEven();
        }
    }
    

    public class OEApp {
    
        public static void main(String[] args) {
    
            SomeMaths sm = new SomeMaths();
    
            Thread odd = new Thread(new Odd(sm));
            Thread even = new Thread(new Even(sm));
    
            odd.start();
            even.start();
    
            try {
                odd.join();
                even.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

2 个答案:

答案 0 :(得分:6)

我相信它的运作方式如下:

  1. 即使是线程开始,1也是奇数,所以它调用notify(通知没有人),然后2就是如此,它会打印一条消息并等待

  2. 奇数线程开始,1是奇数,所以它打印一条消息并等待

  3. 没有人可以调用通知,因此两个线程都会永远等待

答案 1 :(得分:-2)

使用同步关键字的目的是什么?
它只能向您保证您的功能不会同时运行多次。

我假设你想要一个线程通知另一个线程?是吗?
但是,如果在等待之前调用通知会怎么样?

你知道你可以使用调试器来查看每个线程,从而知道每个线程被卡住的位置吗?

请记住,一旦调用 start ,就无法知道哪个线程有cpu时间。

此外,您正在尝试同步两个线程(通过使用通知/等待机制),但还有其他的机制可以证明更简单(例如信号量:每个线程都拥有它< strong>信号量,获取自己的信号量并释放另一个信号量;将每个信号量初始化为1并且它将顺利进行。

P.S。 :