如何用一张图展示synchronized的原理?
世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。
然后详细分析一下:
首先,如果是单线程情况下,没有其它线程与当前线程抢锁,所以当前线程会很容易的通过CAS抢到锁,这时对象头中记录锁信息的位置会将状态记录为当前加锁的线程的线程Id。而由于没有其他线程再需要锁,所以当前线程加锁以后可以一直拥有,而无需解锁,这种单线程加锁以后不需解锁的状态被称为偏向锁。在JDK6以后,synchronized在单线程时默认加偏向锁。
然后,当有多个线程时,就会出现多线程个通过CAS抢锁的现象,这样就由偏向锁状态转向轻量级锁。当有一个线程通过CAS抢到锁,其他线程仍然在通过CAS自旋抢锁,如果抢不到锁一直持续下去就会大量消耗CPU资源,使CPU使用率达到100%。
这样下去肯定是不行的,幸亏我们有Object Monitor(对象监视器),Object Monitor会记录线程抢锁时CAS自旋的次数,当一个线程通过CAS抢锁自旋达到一定次数仍然抢不到锁时,就会被挂起加入到Object Monitor的EntryList(等待队列中),这样就避免了因为持续的CAS自旋而白白浪费CPU资源,当有线程释放锁时,等待队列中的线程就会被取出继续加入到CAS自旋抢锁的大军中去。而这个状态就被称为重量级锁。
当然,如果在多线程到来时单线程释放了它所拥有的的锁或是一开始就有多线程抢锁,那么就会从未锁定状态进入轻量级锁,进而进入重量级锁状态。