1. wait notify
/** * 解释: 唤醒一个等待monitor的线程, 如果有多个线程在等待,会唤醒一个。
* 一个线程在等待monitor是由Object.wait引起的
* 获取一个类的monitor方法有三种
* 1) 执行该类具有synchronizes 的实例方法
* 2) 执行该类具有synchronizes 的静态方法
* 3) 代码同步块synchronizes(Object)
* 如果当前线程没有monitor那么将 throw IllegalMonitorStateException
*/
public final native void notify();
/** * 解释:让当前线程去等待,知道当前其他的线程, 并且 当前线程 必须是monitor的拥有者
*
* 1) 如果超时 throw IllegalArgumentException
* 2) 如果当前线程没有拥有这个Objeect的 monitor throw IllegalMonitorStateException
* 3) 如过当前线程在wait 这个线程被interrrupt 那么 会 throw InterruptedException
* @Param timeout 最大等待时间 (0 是无限长) 单位毫秒
*/
public final native void wait(long timeout) throws InterruptedException;
2.synchronized
一种 同步的 关键字 , 实现: 每个Object都有一个Monitor 也因此 synchronized 是基于这个monitor实现的 并发 安全, 同时 也有自旋 和 ReentLock差不多, 但是是JVM实现 看不到源码不wangjia评论。
3. park, unpark.
和 wait Notify 不同的是 他是 对线程而言的 , 而wait是Object的。 底层似乎是直接用的C的同步信号量
/* 阻塞一个线程直到出现、线程 被中断或者timeout时间到期。如果一个unpark调用已经出现了, * 这里只计数。timeout为0表示永不过期.当isAbsolute为true时 timeout是相对于新纪元之后的毫秒。否则这个值就是超时前的纳秒数。
* 这个方法执行时也可能不合理地返回(没有具体原因) */ public native void park(boolean isAbsolute, long time); /* * 释放被park创建的在一个线程上的阻塞.这个 * 方法也可以被使用来终止一个先前调用park导致的阻塞. * 这个操作操作时不安全的,因此线程必须保证是活的.这是java代码不是native代码。 */ public native void unpark(Thread thread);
下面的代码 会阻塞在 a.wait()
public static void main(String[] args) throws Exception{ Field f = Unsafe.class.getDeclaredField("theUnsafe"); //Internal reference f.setAccessible(true); Unsafe unsafe = (Unsafe) f.get(null); unsafe.unpark(Thread.currentThread()); unsafe.park(false, 0); System.out.println("over"); Integer a = 1; synchronized (a) { a.notify(); } synchronized (a) { a.wait(); } }
我们知道 synchronized Object.wait Object.notify 是一组
而 ReentrantLock 是和 ReentrantLock.Condition.await ReentrantLock.Condition.signal 相对应