面试问题:等待阻塞和锁阻塞有什么区别?
等待是主动的等待,是一个线程等待另一个线程通知调度器一个条件时,该线程进入等待状态。例如调用:Object.wait()、Thread.join()、Thread.sleep()。
ps:经过考察在源码注释中发现LockSupport.park也是waiting状态
阻塞是被动的阻塞,一个线程试图获取一个内部的对象锁(非java.util.concurrent库中的锁),而该锁被其他线程持有,则该线程进入阻塞状态。
线程的 blocked状态往往是无法进入同步方法/代码块来完成的。这是因为无法获取到与同步方法/代码块相关联的锁。
如下图的监视器锁的结构图
引用
详细的执行图,引用
它有多个队列,当多个线程一起访问某个对象监视器的时候,对象监视器会将这些线程存储在不同的容器中。
1.Contention List:竞争队列,所有请求锁的线程首先被放在这个竞争队列中;
2.Entry List:Contention List中那些有资格成为候选资源的线程被移动到Entry List中;
3.Wait Set:哪些调用wait方法被阻塞的线程被放置在这里;
4.OnDeck:任意时刻,最多只有一个线程正在竞争锁资源,该线程被成为OnDeck;
5.Owner:当前已经获取到所资源的线程被称为Owner;
6.!Owner:当前释放锁的线程。
ps:详细执行图比第一张图更贴近事实,因为第一张图会让人误以为waitset中的线程被notify后直接就可以取竞争onwer,而不是进入entrylist。
图中Entrylist中的线程处于阻塞状态,也就是线程还没有拿到锁。Wait Set中的线程处于等待状态,也就是拿到锁后暂时释放锁(等待条件成熟会再次获取锁)。
线程和其他线程抢锁没抢到,就处于阻塞状态了;(此时线程还没进同步代码块)
线程抢到了锁进了同步代码块,(由于某种业务需求)某些条件下Object.wait()了,就处于了等待状态。(此时线程已经进入了同步代码块)
网友评论