Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 尝试同步两个线程时遇到问题_Java_Multithreading_Synchronized - Fatal编程技术网

Java 尝试同步两个线程时遇到问题

Java 尝试同步两个线程时遇到问题,java,multithreading,synchronized,Java,Multithreading,Synchronized,我试图同步到两个线程,一个打印“ping”,另一个打印“pong”,以打印类似“ping-pong-pong-pong-pong….”的内容。我编写了以下程序来实现这一点,但无法获得预期的结果。我不知道我犯了什么错误。互联网上也有同样的解决方案,但我认为在寻找现成的答案之前,我应该自己试一试 class MyThread implements Runnable{ String val = null; MyThread(String val) { this.val = val;

我试图同步到两个线程,一个打印“ping”,另一个打印“pong”,以打印类似“ping-pong-pong-pong-pong….”的内容。我编写了以下程序来实现这一点,但无法获得预期的结果。我不知道我犯了什么错误。互联网上也有同样的解决方案,但我认为在寻找现成的答案之前,我应该自己试一试

class MyThread implements Runnable{
  String val = null;
  MyThread(String val) {
      this.val = val;
  }

    public void run() {
        while(true){
            PingPong.pintMessage(val);
        }
    }
}

public class PingPong {
   static Integer turn = 1;

   public static void main(String args []) {
       Thread t1 = new Thread(new MyThread("ping"));
       Thread t2 = new Thread(new MyThread("pong"));
       t1.start();
       t2.start();

   }
   public static void pintMessage(String msg) {
       synchronized (turn) {
         if(turn==1) {
             System.out.println(Thread.currentThread().getName()+" "+msg);
             turn=2;
         }
         else {
             System.out.println(Thread.currentThread().getName()+" "+msg);
             turn = 1;
         }
    }
   }
}
输出:

Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
Thread-1 pong
Thread-1 pong
Thread-0 ping
Thread-0 ping
Thread-0 ping
Thread-1 pong
请告知我在这里犯了什么基本错误,以及是否有更好的方法来实现相同的行为。谢谢

在进行建议的更改后:我尝试使用wait/notify使用线程通信,但得到了非法的MonitorStateException。我猜我在获取锁定的对象上使用了wait/notify(在同步上下文中使用wait/notify)。请帮助我理解这个概念的微妙之处。塞纳克斯

class MyThread implements Runnable{
    String val = null;

    MyThread(String val) {
        this.val = val;
    }

    public void run() {
        while(true){
            try {
                PingPong.printMessage(val);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

public class PingPong {
    static Integer turn = 1;

    public static void main(String args []) {
        Thread t1 = new Thread(new MyThread("ping"));
        Thread t2 = new Thread(new MyThread("pong"));
        t1.start();
        t2.start();
    }
    public static void printMessage(String msg) throws InterruptedException {
        synchronized (turn) {
            if(turn==1) {
                System.out.println(Thread.currentThread().getName()+" "+msg);
                turn=2;
            }
            else {
                System.out.println(Thread.currentThread().getName()+" "+msg);
                turn = 1;
            }
            turn.notifyAll();
            turn.wait();
        }
    }
}

Output :
Thread-0 ping
Exception in thread "Thread-0" Thread-1 pong
java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at PingPong.printMessage(PingPong.java:40)
    at MyThread.run(PingPong.java:12)
    at java.lang.Thread.run(Unknown Source)

在你的
pintMessage
中,无论
turn
的值是多少,你都会打印一些东西。

在你的
pintMessage中,无论
turn
的值是多少,你都会打印一些东西。

你把
同步的概念弄错了

JVM确保始终只有进程在执行同步块,但它不控制请求进程,这意味着它只按照调用该块的顺序处理调用

在您的情况下:在JVM将循环设置为后台供另一个线程执行之前,每个线程都有机会多次执行循环

如果要确保特定顺序,必须使用
wait()
notify()
/
notifyAll()
: ([编辑]:此代码可能无法正常工作(未测试),只是为了演示原理…)


有关mor信息,请参见此处您将
同步的概念理解错误

JVM确保始终只有进程在执行同步块,但它不控制请求进程,这意味着它只按照调用该块的顺序处理调用

在您的情况下:在JVM将循环设置为后台供另一个线程执行之前,每个线程都有机会多次执行循环

如果要确保特定顺序,必须使用
wait()
notify()
/
notifyAll()
: ([编辑]:此代码可能无法正常工作(未测试),只是为了演示原理…)


有关mor信息,请参见此处

您得到了什么输出?嗨,我刚刚编辑了这个问题以反映获得的输出。谢谢
printMessage
不能保证ping线程的圈数始终为1,而pong线程的圈数始终为2。就方法而言,圈数与当前执行的线程无关。要获得所需的输出,您需要找到一种在线程之间通信的方法,以便ping知道它的作用turn@conscells:如果你能建议一种方法,让ping线程知道是否轮到你了,那会很有帮助。我没有提到,因为你说你不想要一个现成的答案。但您可以研究线程信令或阻塞队列,以使多个线程协作。我也建议你去看看。你得到了什么输出?嗨,吓人的是,我刚刚编辑了这个问题,以反映获得的输出。谢谢
printMessage
不能保证ping线程的圈数始终为1,而pong线程的圈数始终为2。就方法而言,圈数与当前执行的线程无关。要获得所需的输出,您需要找到一种在线程之间通信的方法,以便ping知道它的作用turn@conscells:如果你能建议一种方法,让ping线程知道是否轮到你了,那会很有帮助。我没有提到,因为你说你不想要一个现成的答案。但您可以研究线程信令或阻塞队列,以使多个线程协作。我也建议你去。
class MyThread implements Runnable{
  private Object other;
  public void setOther (MyThread other){
    this.other = other;

  }
  //no changes
       while(true){
            PingPong.pintMessage(val);
            notifyAll();
            other.wait();
        }

}

public static void pintMessage(String msg) {
    synchronized (turn) {
     // no changes
      // MyThread.semaphore.notifyAll();
 }
}