为什么线程t1会出现illegalmonitorstateexception

doinxwow  于 2021-08-20  发布在  Java
关注(0)|答案(1)|浏览(464)

我得到下面代码的这个错误

  1. First thread about to sleep
  2. thread 1 run
  3. Boolean assignment done.
  4. Woke up and about to invoke wait()
  5. Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
  6. at java.lang.Object.wait(Native Method)
  7. at java.lang.Object.wait(Object.java:502)
  8. at IncorrectSynchronization$1.run(HelloWorld.java:23)
  9. at java.lang.Thread.run(Thread.java:748)

当线程t1处于休眠状态时,我将另一个线程的锁修改为false。然后抛出这个非法的MonitorStateException。它仍然是同一个对象,为什么修改值会导致illegalmonitorstateexception?
当我从同步块中的另一个线程将锁修改为false时,我不再得到该错误。有人能解释引擎盖下发生的事情的原因吗?

  1. public class HelloWorld{
  2. public static void main( String args[] ) throws InterruptedException {
  3. SampleTest.runExample();
  4. }
  5. }
  6. class SampleTest{
  7. Boolean flag = new Boolean(true);
  8. public void example() throws InterruptedException {
  9. Thread t0 = new Thread(new Runnable() {
  10. public void run() {
  11. synchronized (flag) {
  12. try {
  13. while (flag) {
  14. System.out.println("First thread about to sleep");
  15. Thread.sleep(2000);
  16. System.out.println("Woke up and about to invoke wait()");
  17. flag.wait();
  18. System.out.println("wait() called");
  19. }
  20. } catch (InterruptedException ie) {
  21. }
  22. }
  23. }
  24. });
  25. Thread t1 = new Thread(new Runnable() {
  26. public void run() {
  27. System.out.println("thread 1 run");
  28. flag = false;
  29. }
  30. });
  31. t0.start();
  32. Thread.sleep(200);
  33. t1.start();
  34. t0.join();
  35. t1.join();
  36. }
  37. public static void runExample() throws InterruptedException {
  38. SampleTest test = new SampleTest();
  39. test.example();
  40. }
  41. }
rqqzpn5f

rqqzpn5f1#

这一行的问题在于:

  1. flag = false;

这将更改 flag 布尔变量,来自原始 Boolean 对象(它是由不推荐使用的构造函数创建的,不应使用该构造函数)添加到预创建的 Boolean.FALSE 示例(由于自动装箱)。当第一个线程调用 flag.wait() ,对象不再与用于同步的对象相同,因此 IllegalMonitorStateException .
在这种情况下,最好使用 AtomicBoolean 并在另一个线程中改变其值:

  1. AtomicBoolean flag = new AtomicBoolean(true);

现在,第二个线程可以更新同一对象的值。它还可能通知等待对象的第一个线程(如 wait() , notify() 还需要在调用它的对象上进行同步):

  1. Thread t1 = new Thread(new Runnable() {
  2. public void run() {
  3. synchronized(flag) {
  4. System.out.println("thread 1 run");
  5. flag.set(false);
  6. flag.notify();
  7. }
  8. }
  9. });
展开查看全部

相关问题