阻塞和等待有啥区别

阻塞是争抢锁失败后被动触发、等待是人为主动触发

阻塞是持锁线程结束后自动唤醒,而等待需要人为用特定的方法唤醒

触发方式:阻塞是在争抢sychronized锁过程中失败后触发,一直到持有锁的线程结束再次争夺锁;WATING是通过Object.wait()方法来触发,此时线程必须持有锁才能触发,而Thread.join()、LockSupport.park()触发的话就不需要持有锁,也不会占用cpu资源

唤醒方式:需要等到持锁线程执行结束再次自动唤醒,而WATING的话如果是wait()进入的就需要用其对象的notify()或notifyAll()这样的方法来唤醒,若是Thread.join()等待执行线程结束后即可唤醒,LockSupport.park()的话需要用LockSupport.unparkthread

等待状态下的线程如何进行恢复到运行状态?

核心机制是通过外部事件触发或资源可用性变化,比如等待的线程被其他线程唤醒

synchronized (lock) {
    // 线程进入等待状态,释放锁
    lock.wait(); 
}

// 其他线程调用以下代码唤醒等待线程
synchronized (lock) {
    lock.notify();      // 唤醒单个线程
    // lock.notifyAll(); // 唤醒所有等待线程
}

notify(通知)和notifyAll有什么区别?

都是唤醒线程、都是唤醒线程来竞争锁、都是无法确定谁来竞争锁

notify:唤醒一个线程,让唤醒的线程来拿到锁执行线程,执行线程后如果该线程没有调用notify,那么其他线程都没有办法来苏醒得到锁

notifyAll:唤醒所有的线程,让所有的线程来争夺同一个锁,只有一个线程才能得到锁,得到锁的线程结束后,其他线程还可以争抢锁,直到一个对象的线程所有执行完成

notify选择哪个线程唤醒?

notify 在注释中提到,但是 notify 选择唤醒线程的源码是任意的,依赖于具体实现的 jvm。

比较流行实现的jvm就是hotspot(热点),其唤醒顺序是先进入对象等待队列的线程先唤醒,也就是说先调用wait()方法的线程优先唤醒

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐