// 返回实例运行时的的类型
public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public final native void notify();
public final native void notifyAll();
public final void wait() throws InterruptedException {
wait(0);
}
public final void wait(long timeout, int nanos) throws InterruptedException;
public final native void wait(long timeout) throws InterruptedException
protected void finalize() throws Throwable { }
- wait() 导致当前线程进入waiting状态,直至另一个线程调用notify()、notifyAll()方法
- 当前线程(调用wait()的线程)必须拥有这个对象的(monitor)锁,然后线程释放这个(monitor)锁
synchronized (obj) {
while (condition does not hold)
obj.wait();
... // Perform action appropriate to condition
}
- notify() 唤醒一个等待对象锁的线程
- 只有等当前线程释放了对象锁之后,被唤醒的线程才能够proceed(运行)
- 被唤醒的线程会和其他线程一样去竞争对象锁资源。
- 只有拥有对象锁资源的线程才能调用此方法
一个线程获得对象锁(monitor监视器)资源的三种方法(synchronized的三种用法):
- By executing a synchronized instance method of that object.
- By executing the body of a {@code synchronized} statement that synchronizes on the object.
- For objects of type {@code Class,} by executing a synchronized static method of that class.
总结
synchronized(object1) {
object1.wait();
System.out.printLn("hello")
}
首先一个线程A尝试获取object1对象的monitor锁,
其实是将object1对象的mark word中引用的MonitorObject对象的_owner设置为当前线程。
如果这时候会有另一个线程B过来,尝试进入同步代码块,尝试获取锁失败,然后会自旋一会,
如还没有成功获取锁,则会将线程B会进入BLOCKED状态,然后线程B被封装成ObjectWaiter
放置object1对象的mark word中引用的MonitorObject对象的_EntryList里。
然后线程A会调用object1.wait();线程A会释放占用的monitor锁,
即 将object1对象的mark word中引用的MonitorObject对象的_owner设置为null。
然后线程A进入WAITING状态,且被被封装成ObjectWaiter放置object1对象的
mark word中引用的MonitorObject对象的_WaitSet里。
synchronized(object1) {
object1.signal();
}
此时线程C恰好尝试获取object1对象锁,正在自旋,恰好获得了object1对象锁,
这时object1对象的mark word中引用的MonitorObject对象的_owner为线程C。
线程C里调用object1.signal();然后会在object1对象的mark word中引用的
MonitorObject对象的_WaitSet里,随机挑选一个ObjectWaiter并唤醒该线程,
这时线程C还没有释放object1对象锁。
假设恰好唤醒线程A,这时线程A和_EntryList里的线程会竞争锁,
然后当线程A获得监视器锁,将会在直接打印"hello",说明被唤醒后的位置是在await()之后。
被唤醒的线程要从哪里恢复执行呢?当然是被挂起的地方
等待/通知的经典范式
synchronized (对象) {
while (条件不满足) {
对象.wait();
}
对应的逻辑处理
}
synchronized (对象) {
改变条件
对象.notify();
}