Well, when we wait() we have to release a lock that we hold and wait for it again. When we notify() [or notifyAll()] we tell another waiting thread [or other waiting threads] that we are finished with a lock. See the problem now? What lock? We need to first synchronize on an object to get hold of the object's lock.