存在層次上
synchronized: Java的關(guān)鍵字,在jvm層面上
Lock: 是一個(gè)接口
鎖的釋放
synchronized: 1、以獲取鎖的線程執(zhí)行完同步代碼,釋放鎖 2、線程執(zhí)行發(fā)生異常,jvm會(huì)讓線程釋放鎖
Lock: 在finally中必須釋放鎖,不然容易造成線程死鎖
鎖的獲取
synchronized: 假設(shè)A線程獲得鎖,B線程等待。如果A線程阻塞,B線程會(huì)一直等待
Lock: 分情況而定,Lock有多個(gè)鎖獲取的方式,大致就是可以嘗試獲得鎖,線程可以不用一直等待(可以通過tryLock判斷有沒有鎖)
鎖的釋放(死鎖產(chǎn)生)
synchronized: 在發(fā)生異常時(shí)候會(huì)自動(dòng)釋放占有的鎖,因此不會(huì)出現(xiàn)死鎖
Lock: 發(fā)生異常時(shí)候,不會(huì)主動(dòng)釋放占有的鎖,必須手動(dòng)unlock來釋放鎖,可能引起死鎖的發(fā)生
鎖的狀態(tài)
synchronized: 無法判斷
Lock: 可以判斷
鎖的類型
synchronized: 可重入 不可中斷 非公平
Lock: 可重入 可判斷 可公平(兩者皆可)
性能
synchronized: 少量同步
Lock: 大量同步
Lock可以提高多個(gè)線程進(jìn)行讀操作的效率。(可以通過readwritelock實(shí)現(xiàn)讀寫分離)
在資源競爭不是很激烈的情況下,Synchronized的性能要優(yōu)于ReetrantLock,但是在資源競爭很激烈的情況下,Synchronized的性能會(huì)下降幾十倍,但是ReetrantLock的性能能維持常態(tài);
ReentrantLock提供了多樣化的同步,比如有時(shí)間限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在資源競爭不激烈的情形下,性能稍微比synchronized差點(diǎn)點(diǎn)。但是當(dāng)同步非常激烈的時(shí)候,synchronized的性能一下子能下降好幾十倍。而ReentrantLock確還能維持常態(tài)。
調(diào)度
synchronized: 使用Object對象本身的wait 、notify、notifyAll調(diào)度機(jī)制
Lock: 可以使用Condition進(jìn)行線程之間的調(diào)度
用法
synchronized: 在需要同步的對象中加入此控制,synchronized可以加在方法上,也可以加在特定代碼塊中,括號中表示需要鎖的對象。
Lock: 一般使用ReentrantLock類做為鎖。在加鎖和解鎖處需要通過lock()和unlock()顯示指出。所以一般會(huì)在finally塊中寫unlock()以防死鎖。
底層實(shí)現(xiàn)
synchronized: 底層使用指令碼方式來控制鎖的,映射成字節(jié)碼指令就是增加來兩個(gè)指令:monitorenter和monitorexit。當(dāng)線程執(zhí)行遇到monitorenter指令時(shí)會(huì)嘗試獲取內(nèi)置鎖,如果獲取鎖則鎖計(jì)數(shù)器+1,如果沒有獲取鎖則阻塞;當(dāng)遇到monitorexit指令時(shí)鎖計(jì)數(shù)器-1,如果計(jì)數(shù)器為0則釋放鎖。
Lock: 底層是CAS樂觀鎖,依賴AbstractQueuedSynchronizer類,把所有的請求線程構(gòu)成一個(gè)CLH隊(duì)列。而對該隊(duì)列的操作均通過Lock-Free(CAS)操作。