背景
在并发编程学习中,学习到wait、sleep方法的时候,突然有个想法,为什么wait方法要归属于Object类,而不是Thread类那?不都是线程相关的吗?于是搜索了下,整理完后,自己感觉好像懂了又不是很清楚,先做个记录,回头等并发编程都看完了,回头再来看一遍,希望那时候,可以清除的说出来。
为什么java中的wait方法是object类的
在Java中,wait()、notify() 和 notifyAll() 方法是定义在 Object 类中的,而不是 Thread 类。这是因为 Java 的并发控制机制基于对象的锁(也称为监视器或monitor),而非线程本身。以下是一些原因解释为什么这些方法适用于任何对象,而不是线程对象:
-
同步机制与对象关联:Java 中的同步是基于对象的,而不是线程。当一个线程进入一个同步方法或代码块时,它会获取该方法所属对象的内部锁(即监视器)。因此,
wait()和notify()等方法需要作用于这个锁所关联的对象,以确保多个线程可以协调对共享资源的访问。 -
保护共享资源:通常,
wait()用于等待某个条件发生,而这个条件通常是关于共享资源的状态。因为共享资源是由对象表示的,所以这些方法必须作用于包含共享资源的对象,以便不同线程之间能够就这些资源的状态进行通信。 -
避免死锁和竞态条件:如果
wait()和notify()是线程的方法,那么就很难保证线程间的正确协作,容易导致死锁或竞态条件。通过将它们设计为对象的方法,Java 确保了线程只能在持有特定对象的锁的情况下调用wait(),这有助于防止这些问题。 -
灵活性和复用性:由于所有类都是
Object类的子类,因此所有对象都可以使用这些同步方法。这意味着开发者可以在任何地方使用这些方法来实现复杂的同步逻辑,而不需要依赖特定的线程类。 -
统一的接口:将
wait()和notify()定义在Object类中提供了一个统一的接口,使得所有的对象都有相同的同步能力,简化了并发编程模型。
使用 wait() 和 notify() 的注意事项
- 必须在同步上下文中调用:
wait()、notify()和notifyAll()必须在一个同步方法或同步代码块中被调用,也就是说,当前线程必须拥有调用wait()或notify()的对象的锁。 wait()释放锁:当线程调用wait()时,它会释放该对象的锁,并进入等待状态,直到其他线程调用了同一个对象上的notify()或notifyAll()方法。notify()不一定唤醒正确的线程:如果你有多个线程在同一个对象上等待,notify()只会随机唤醒其中一个线程,而notifyAll()则会唤醒所有等待的线程。通常建议使用notifyAll()来避免潜在的竞态条件。
总之,wait() 和 notify() 方法设计为 Object 类的方法,是为了支持基于对象的同步机制,这是 Java 并发编程的一个核心概念。