通过提供的代码示例,我们看到作者意图是使用 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 对象仅用于传递当前打印线程标识,从而解决了锁修改问题和死锁的可能性。