(1)ReentrantLock擁有Synchronized相同的并發(fā)性和內(nèi)存語(yǔ)義,兩者都是可重入的鎖;Lock的實(shí)現(xiàn)依賴于cpu級(jí)別的指令控制,Synchronized的實(shí)現(xiàn)主要由JVM實(shí)現(xiàn)控制
(2)synchronized不但可以通過(guò)一些監(jiān)控工具監(jiān)控synchronized的鎖定,而且在代碼執(zhí)行時(shí)出現(xiàn)異常,JVM會(huì)自動(dòng)釋放鎖定;但是使用Lock則不行,lock是通過(guò)代碼實(shí)現(xiàn)的,要人為保證鎖定一定會(huì)被釋放,就必須將unLock()放到finally{}中,否則可能造成死鎖現(xiàn)象
(3)synchronized不是可中斷鎖,而ReentrantLock是可中斷鎖。Lock可以讓等待鎖的線程響應(yīng)中斷,而synchronized卻不行,使用synchronized時(shí),等待的線程會(huì)一直等待下去,不能夠響應(yīng)中斷;
(4)通過(guò)ReentrantLock可以知道有沒(méi)有成功獲取鎖,而synchronized卻無(wú)法辦到。
(5)synchronized是非公平鎖,而ReentrantLock默認(rèn)實(shí)現(xiàn)是非公平鎖,但提供公平鎖的實(shí)現(xiàn);
(6)ReentrantLock提供讀寫(xiě)兩種鎖操作;
(5)在資源競(jìng)爭(zhēng)不是很激烈的情況下,Synchronized的性能要優(yōu)于ReetrantLock,原因在于,編譯程序通常會(huì)盡可能的進(jìn)行優(yōu)化synchronized,另外可讀性非常好;
但是在資源競(jìng)爭(zhēng)很激烈的情況下,Synchronized的性能會(huì)下降幾十倍,但是ReetrantLock的性能能維持常態(tài);ReentrantLock提供了多樣化的同步,比如有時(shí)間限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。
(6)Atomic: 和上面的類(lèi)似,不激烈情況下,性能比synchronized略遜,而激烈的時(shí)候,也能維持常態(tài)。激烈的時(shí)候,Atomic的性能會(huì)優(yōu)于ReentrantLock一倍左右。但是其有一個(gè)缺點(diǎn),就是只能同步一個(gè)值,一段代碼中只能出現(xiàn)一個(gè)Atomic的變量,多于一個(gè)同步無(wú)效。因?yàn)樗荒茉诙鄠€(gè)Atomic之間同步。
概念
可重入鎖:可重入鎖是指同一個(gè)線程可以多次獲取同一把鎖。
可中斷鎖:是指線程嘗試獲取鎖的過(guò)程中,是否可以響應(yīng)中斷。
公平鎖:是指多個(gè)線程同時(shí)嘗試獲取同一把鎖時(shí),獲取鎖的順序按照線程達(dá)到的順序,而非公平鎖則允許線程“插隊(duì)”。
性能比較:
在JDK1.5中,synchronized的性能是比較低的,線程阻塞和喚醒由操作系統(tǒng)內(nèi)核完成,頻繁的加鎖和放鎖導(dǎo)致頻繁的上下文切換,造成效率低下;因此在多線程環(huán)境下,synchronized的吞吐量下降的非常嚴(yán)重。但在JDK1.6時(shí)對(duì)synchronized進(jìn)行了很多優(yōu)化,包括偏向鎖、自適應(yīng)自旋、輕量級(jí)鎖等措施。
當(dāng)需要以下高級(jí)特性時(shí),才應(yīng)該使用Lock:可定時(shí)的、可輪詢的與可中斷的鎖獲取操作,公平隊(duì)列,或者非塊結(jié)構(gòu)的鎖。否則,請(qǐng)使用synchronized。
所以,我們寫(xiě)同步的時(shí)候,優(yōu)先考慮synchronized,如果有特殊需要,再進(jìn)一步優(yōu)化。ReentrantLock和Atomic如果用的不好,不僅不能提高性能,還可能帶來(lái)災(zāi)難。
synchronized關(guān)鍵字會(huì)讓沒(méi)有得到鎖資源的線程進(jìn)入BLOCKED狀態(tài),而后在爭(zhēng)奪到鎖資源后恢復(fù)為RUNNABLE狀態(tài),這個(gè)過(guò)程中涉及到操作系統(tǒng)用戶模式和內(nèi)核模式的轉(zhuǎn)換,代價(jià)比較高。
盡管JAVA 1.6為synchronized做了優(yōu)化,增加了從偏向鎖到輕量級(jí)鎖再到重量級(jí)鎖的過(guò)度,但是在轉(zhuǎn)變?yōu)橹亓考?jí)鎖之后,性能仍然比較低。
所以針對(duì)計(jì)數(shù)情況,我們就可以使用java中的“原子操作類(lèi)”。