在synchronized内部包括 ContentionList、EntryList、WaitSet、OnDesk、Owner、!Owner这6个区域,每个区域都代表锁的不同状态。

  • ContentionList:锁竞争队列,所以请求锁的线程都被放在竞争队列里。
  • EntryList:竞争候选列表,在ContentionList中有资格成为候选者来竞争锁资源的线程被移动到EntryList中。
  • WaitSet:等待集合,调用wait方法后被阻塞的线程将被放在WaitSet中。
  • OnDesk:竞争候选者,在同一时刻最多只有一个线程在竞争锁资源,该线程的状态被置为OnDesk。
  • Owner:竞争到锁资源的线程被称为Owner状态的线程。
  • !Owner:在Owner线程释放锁后,会从Owner的状态变为!Owner

        synchronized 在收到新的锁请求时首先自旋,如果通过自旋也没有获取到锁资源,则将被放入锁竞争队列ContentionList中。

        为防止锁竞争是ContentionList尾部的元素被大量的并发线程进行CAS访问而影响性能,Owner线程会在释放锁资源时将 ContentionList 中的部分线程移动到EntryList中,并指定EntryList中的某个线程(一般是最先进入的线程)为OnDeck线程。让OnDeck重新竞争锁。在Java中把该行为称为“竞争切换”,该行为牺牲了公平性,但提高了性能。

        获得锁的资源的OnDeck线程会变成Owner线程,而未获取到锁资源的线程仍停留在EntryList中。 Owner线程在被wait方法阻断后,会转移到WaitSet队列中,知道某个时刻被notify方法或者notifyAll方法唤醒,