锁定 Condition.notify 抛出 java.lang.IllegalMonitorStateException

Lock Condition.notify is throwing java.lang.IllegalMonitorStateException

提问人:Kris Jobs 提问时间:8/17/2023 最后编辑:Kris Jobs 更新时间:8/18/2023 访问量:55

问:

我编写了一个程序来演示用于多线程目的的 java 的 Lock.Condition。我收到 IllegalMonitorStateException。

它抛出一个异常,输出如下。

我在调用通知之前获取锁定。但仍然出现以下错误。有人可以帮忙吗?我用谷歌搜索了很多,但找不到解决方案。

Count : 0
lock java.util.concurrent.locks.ReentrantLock@4ce4d37e[Locked by thread Thread-0]
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current thread is not owner
at java.base/java.lang.Object.notify(Native Method)
at test.OddEvenPrinter.printEven(Test.java:51)
    at test.Test.lambda$main$1(Test.java:22)
at java.base/java.lang.Thread.run(Thread.java:1589)
Count : 1
lock java.util.concurrent.locks.ReentrantLock@4ce4d37e[Locked by thread Thread-1]
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException: current thread is not owner
    at java.base/java.lang.Object.notify(Native Method)
    at test.OddEvenPrinter.printOdd(Test.java:67)
    at test.Test.lambda$main$0(Test.java:14)
    at java.base/java.lang.Thread.run(Thread.java:1589)

它的代码如下:

package test;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
    public static void main(String[] args) {
        final OddEvenPrinter oddEvenPrinter = new OddEvenPrinter();
        Runnable oddRunnable = () -> {
            try {
                while (true)
                    oddEvenPrinter.printOdd();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable evenRunnable = () -> {
            try {
                while (true)
                    oddEvenPrinter.printEven();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        new Thread(evenRunnable).start();
        new Thread(oddRunnable).start();
    }
}

class OddEvenPrinter {
    private final Lock lock = new ReentrantLock();
    private final Condition oddPrint = lock.newCondition();
    private final Condition evenPrint = lock.newCondition();
    private int count;
    public void printEven() throws InterruptedException {
        lock.lock();
        try {
            Thread.sleep(3000);
            while (count % 2 == 1) {
                evenPrint.await();
            }
            System.out.println("Count : " + count++);
            System.out.println("lock " + lock);
            oddPrint.notify();
        } finally {
            lock.unlock();
        }
    }
    public void printOdd() throws InterruptedException {
        lock.lock();
        try {
            Thread.sleep(2000);
            while (count % 2 == 0) {
                oddPrint.await();
            }
            System.out.println("Count : " + count++);
            System.out.println("lock " + lock);
            evenPrint.notify();
        } finally {
            lock.unlock();
        }
    }
}
Java 多线程 条件语句 锁定 通知

评论

2赞 Denis Zavedeev 8/17/2023
使用时,我们应该使用 or 方法。和 是与内部锁相关的方法(带有关键字)java.util.concurrent.locks.ConditionsignalsignalAllnotifynotifyAllsynchronized
0赞 Kris Jobs 8/18/2023
我需要使用信号而不是通知。这只是与方法名称的混淆。
0赞 Denis Zavedeev 8/18/2023
是的,很容易错过。Intellij IDEA 甚至对它进行了检查,它的名称是“在 java.util.concurrent.locks.Condition 对象上调用的 notify() 或 notifyAll()”。发布为答案

答:

2赞 Denis Zavedeev 8/18/2023 #1

使用时,我们应该使用 or 方法。java.util.concurrent.locks.ConditionsignalsignalAll

例:

public void foo() {
    reentrantLock.lock();
    try {
        condition.signal();
    } finally {
        reentrantLock.unlock();
    }
}

和 是与内部锁相关的方法(带有关键字),例如:notifynotifyAllsynchronized

public synchronized void foo() throws InterruptedException {
    this.notify();
}
2赞 Kris Jobs 8/18/2023 #2

当我使用锁定条件时,我使用了通知而不是使用信号方法。

我正在粘贴更正后的代码。

package test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test {

    public static void main(String[] args) {
        final OddEvenPrinter oddEvenPrinter = new OddEvenPrinter();
        Runnable oddRunnable = () -> {
            try {
                while (true)
                    oddEvenPrinter.printOdd();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable evenRunnable = () -> {
            try {
                while (true)
                    oddEvenPrinter.printEven();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        new Thread(evenRunnable).start();
        new Thread(oddRunnable).start();
    }
}

class OddEvenPrinter {

    private final Lock lock = new ReentrantLock();

    private final Condition oddPrint = lock.newCondition();

    private final Condition evenPrint = lock.newCondition();

    private int count;

    public void printEven() throws InterruptedException {
        lock.lock();
        try {
            Thread.sleep(3000);
            while (count % 2 == 1) {
                evenPrint.await();
            }
            System.out.println("Count : " + count++);
            System.out.println("lock " + lock);
            oddPrint.signal();
        } finally {
            lock.unlock();
        }

    }

    public void printOdd() throws InterruptedException {
        lock.lock();
        try {
            Thread.sleep(2000);
            while (count % 2 == 0) {
                oddPrint.await();
            }
            System.out.println("Count : " + count++);
            System.out.println("lock " + lock);
            evenPrint.signal();
        } finally {
            lock.unlock();
        }

    }
}