synchronized 和 ReentrantLock 的實現(xiàn)原理是什么?它們有什么區(qū)別
synchronized 和 ReentrantLock 的實現(xiàn)原理是什么
synchronized 屬于獨占式悲觀鎖,是通過 JVM 隱式實現(xiàn)的,synchronized 只允許同一時刻只有一個線程操作資源。
Java 中每個對象都隱式包含一個 monitor(監(jiān)視器)對象,加鎖的過程其實就是競爭 monitor 的過程,當(dāng)線程進(jìn)入字節(jié)碼 monitorenter 指令之后,線程將持有 monitor 對象,執(zhí)行 monitorexit 時釋放 monitor 對象,當(dāng)其他線程沒有拿到 monitor 對象時,則需要阻塞等待獲取該對象。
ReentrantLock 是 Lock 的默認(rèn)實現(xiàn)方式之一,它是基于 AQS(Abstract Queued Synchronizer,隊列同步器)實現(xiàn)的,它默認(rèn)是通過非公平鎖實現(xiàn)的,在它的內(nèi)部有一個 state 的狀態(tài)字段用于表示鎖是否被占用,如果是 0 則表示鎖未被占用,此時線程就可以把 state 改為 1,并成功獲得鎖,而其他未獲得鎖的線程只能去排隊等待獲取鎖資源。
synchronized 和 ReentrantLock 有什么區(qū)別
synchronized 是 JVM 隱式實現(xiàn)的,而 ReentrantLock 是 Java 語言提供的 API;
ReentrantLock 可設(shè)置為公平鎖,而 synchronized 卻不行;
ReentrantLock 只能修飾代碼塊,而 synchronized 可以用于修飾方法、修飾代碼塊等;
ReentrantLock 需要手動加鎖和釋放鎖,如果忘記釋放鎖,則會造成資源被永久占用,而 synchronized 無需手動釋放鎖;
ReentrantLock 可以知道是否成功獲得了鎖,而 synchronized 卻不行。
公平鎖 VS 非公平鎖
公平鎖的含義是線程需要按照請求的順序來獲得鎖;而非公平鎖則允許“插隊”的情況存在,所謂的“插隊”指的是,線程在發(fā)送請求的同時該鎖的狀態(tài)恰好變成了可用,那么此線程就可以跳過隊列中所有排隊的線程直接擁有該鎖。
而公平鎖由于有掛起和恢復(fù)所以存在一定的開銷,因此性能不如非公平鎖,所以 ReentrantLock 和 synchronized 默認(rèn)都是非公平鎖的實現(xiàn)方式。
