登录
首页 >  文章 >  java教程

多线程wait方法报错:为什么使用wait/notify机制交替打印ABC会抛出IllegalMonitorStateException?

时间:2024-12-26 16:49:02 158浏览 收藏

知识点掌握了,还需要不断练习才能熟练运用。下面golang学习网给大家带来一个文章开发实战,手把手教大家学习《多线程wait方法报错:为什么使用wait/notify机制交替打印ABC会抛出IllegalMonitorStateException?》,在实现功能的过程中也带大家重新温习相关知识点,温故而知新,回头看看说不定又有不一样的感悟!

多线程wait方法报错:为什么使用wait/notify机制交替打印ABC会抛出IllegalMonitorStateException?

多线程 wait 方法报错的根源

通过提供的代码示例,我们看到作者意图是使用 wait/notify 机制来实现三个线程交替打印字符 abc。然而,代码中存在一个错误会导致报出 illegalmonitorstateexception。

错误出在每次线程打印完成后,作者错误地使用了 current_thread 对象来修改当前打印线程标识,同时又试图唤醒其他线程。这造成了一个死锁,因为 current_thread 对象充当锁角色,但其内部数据却在锁释放之前被修改了。

因此,线程 a 在等待其他线程释放锁时,由于锁已被修改,导致无法唤醒,从而抛出了 illegalmonitorstateexception。

解决方案:引入额外的锁对象

为了解决这个问题,我们可以引入一个额外的锁对象,专门用于实现同步,而 current_thread 对象仅用于传递当前打印线程标识。下面给出修改后的代码:

public class Test {
    private static volatile String CURRENT_THREAD = "A";
    private static final Object lock = new Object(); // 额外锁对象

    public static void main(String[] args) {
        Thread t1 = new Thread(new PrintThreadName(), "A");
        Thread t2 = new Thread(new PrintThreadName(), "B");
        Thread t3 = new Thread(new PrintThreadName(), "C");
        t1.start();
        t2.start();
        t3.start();
    }

    static class PrintThreadName implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                synchronized (lock) {
                    while (!CURRENT_THREAD.equals(Thread.currentThread().getName())) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print(CURRENT_THREAD);
                    if (CURRENT_THREAD.equals("A")) {
                        CURRENT_THREAD = "B";
                    } else if (CURRENT_THREAD.equals("B")) {
                        CURRENT_THREAD = "C";
                    } else if (CURRENT_THREAD.equals("C")) {
                        CURRENT_THREAD = "A";
                    }
                    lock.notifyAll();
                }
            }
        }
    }
}

在这个修改后的代码中,我们使用 lock 对象实现同步,而 current_thread 对象仅用于传递当前打印线程标识,从而解决了锁修改问题和死锁的可能性。

文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《多线程wait方法报错:为什么使用wait/notify机制交替打印ABC会抛出IllegalMonitorStateException?》文章吧,也可关注golang学习网公众号了解相关技术文章。

相关阅读
更多>
最新阅读
更多>
课程推荐
更多>