简述为什么 wait(), notify()和 notifyAll ()必须在同步方法或 者同步块中被调用?
参考答案:
wait()
, notify()
, 和 notifyAll()
是 Java 中用于线程间通信的内置方法,它们都是 java.lang.Object
类的一部分。这些方法只能在同步方法或同步块中被调用,这是为了确保线程安全。以下是为什么这些限制存在的原因:
- 防止竞态条件:竞态条件是多线程编程中的一个常见问题,发生在两个或多个线程同时访问共享数据,并且至少有一个线程修改该数据时。如果没有同步,一个线程可能在另一个线程调用
wait()
、notify()
或notifyAll()
之后立即修改对象的状态,导致不可预测的结果。通过要求这些方法在同步块或同步方法中调用,Java 确保了在任何时候只有一个线程可以执行这些操作,从而防止了竞态条件。 - 线程状态转换:
wait()
、notify()
和notifyAll()
方法涉及到线程的状态转换。例如,wait()
会使当前线程进入等待状态,直到其他线程调用notify()
或notifyAll()
。为了正确地管理这些状态转换,Java 需要确保这些调用是在一个受保护的上下文中进行的,这就是同步块或同步方法。 - 对象监视器:在 Java 中,每个对象都有一个内置的锁或监视器,用于同步访问该对象的实例方法。当一个线程进入一个对象的同步方法或同步块时,它必须获得该对象的锁。只有持有该锁的线程才能调用
wait()
、notify()
或notifyAll()
,因为这些方法操作的是对象的内部锁或监视器。
综上所述,为了确保线程安全和正确的同步行为,Java 要求 wait()
, notify()
, 和 notifyAll()
只能在同步方法或同步块中被调用。这有助于防止竞态条件、正确地管理线程状态转换,并确保对对象内部锁的正确访问。