简体   繁体   English

为什么我的代码抛出IllegalMonitorStateException?

[英]Why is my code throwing an IllegalMonitorStateException?

I am trying to understand how threads work in Java. 我试图了解线程如何在Java中工作。 Hence I wrote a small piece of code where by I create two threads, one printing all odd numbers and other printing even numbers, and trying to synchronize between them so that all the numbers are printed in order. 因此,我写了一小段代码,在该代码中,我创建了两个线程,一个线程打印所有奇数,其他线程打印偶数,并尝试在它们之间进行同步,以便按顺序打印所有数字。

public class Main 
{

    public static void main (String args[]){

        Main lock = new Main();

        Test t1 = new Test(1, lock);

        Test t2 = new Test(2, lock);

        synchronized(lock){

            (new Thread(t1)).start();
            (new Thread(t2)).start();

        }


    }

}

public class Test implements Runnable {


    int n;
    Main lock;

    public Test(int newN, Main lockObj){
        this.n = newN;
        this.lock = lockObj;
    }


    public void run() {


        while(true){

            if (n != 1){
                try {
                    lock.wait();
                } catch (InterruptedException e) {

                    e.printStackTrace();
                }
            }

            n = n + 2;

            System.out.println(n);

            lock.notify();

        }


    }


}

Can someone please help understand what the underlying problem is? 有人可以帮助您理解潜在的问题是什么吗?

You have three threads, the main thread, t1 and t2 . 您有三个线程,即main线程t1t2 The thread owning the lock can use actions notify , notifyAll and wait . 拥有锁的线程可以使用动作notifynotifyAllwait In this case the main thread owns the lock not t1 or t2 . 在这种情况下, main线程拥有的锁不是t1t2

You will need to synchronize within the run method of each thread to be able to wait . 您将需要在每个线程的run方法内进行同步才能wait


Here is an example of what I mean by synchronizing in the run method. 这是我在run方法中进行synchronizing意思的示例。

Any operation that happens from the run method after you start the thread will be done by that thread running. 启动线程后, run方法中发生的任何操作都将由该线程运行来完成。 So when you try and wait you will want to make sure the thread owns the lock, you can do this by synchronizing it in the run method. 因此,当您尝试wait您将要确保线程拥有锁,可以通过在run方法中对其进行同步来做到这一点。

public void run() {
     synchronized(lock){
         while(true){
            if (n != 1){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
               }
            }
            n = n + 2;
            System.out.println(n);
            lock.notify();
        }
    }
}

As you can see I am synchronizing within the run method so that t1 and t2 own the locks while notifying or waiting. 如您所见,我正在run方法中进行同步,以便t1t2在通知或等待时拥有锁。

This will probably not help you understanding the low-level threading mechanics, but for your case it would make sense to use a CyclicBarrier with a barrierAction. 这可能不会帮助您了解底层的线程机制,但是对于您而言,将CyclicBarrierCyclicBarrier一起使用是有意义的。

Make both treads wait on the barrier after processing n = n + 2 , let the barrierAction sysout both thread's current n , repeat. 在处理n = n + 2 ,使两个踏步都在障碍上等待,让barrierAction sysout重复两个线程的当前n

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM