作為一名程式員,在求職面試時,不知道你在求職面試時常會遇到關于線程的問題。
張工是一名java程式員,3年多工作經驗,有次到一家網際網路公司面試軟體開發工程師崗位,面試官就問了他這樣一個問題。
synchronized與Lock有什麼差別?
張工回答得不是很理想,面試官就說,你都工作3年多了,怎麼連synchronize和Lock差別都沒掌握。
聽面試官這麼一說,張工頓時不好意思,感覺這次面試估計要黃了。
對于這個問題,我在面試時我就曾遇到過,當時回答也不是很理想,今天簡單梳理下synchronized與Lock兩者之間有什麼差別。
我們知道,synchronized與Lock都是鎖,synchronized是java中的一個關鍵字,也就是說是Java語言内置的特性,那麼為什麼會出現Lock 鎖呢。兩者之間有什麼差別呢。
對于synchronized相信你并不陌生,我們時常會看到有一段代碼塊被synchronized修飾了,當一個線程擷取了對應的鎖,并執行該代碼塊時,其他線程便隻能一直等待,等待擷取鎖的線程釋放鎖。
這裡擷取鎖的線程釋放鎖會出現下面這兩種情況:
- 擷取鎖的線程執行完了該代碼塊,然後線程釋放對鎖的占有權;
- 線程執行發生異常,此時JVM會讓線程自動釋放鎖。
在這釋放鎖的過程彙總,要是擷取鎖的線程由于要等待IO被阻塞了,但是又沒有及時釋放鎖,那麼其他線程隻能一直等待,這樣就顯得很被動,對程式執行效率有很大的影響,使用者體驗會很差。
這時候Lock就派上用場了,Lock可以不讓等待的線程一直無期限地等待下去,比如在一定的時間就能夠做到響應中斷。
另外,從代碼層看,Lock是一個接口
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
Lock
其中lock()、tryLock()、tryLock(long time, TimeUnit unit)和lockInterruptibly()方法是用來擷取鎖的。unLock()方法是用來釋放鎖的。
簡單來說,Lock和synchronized有什麼差別:
- Lock是一個接口,而synchronized是Java中的關鍵字;
- synchronized在發生異常時,會自動釋放線程占有的鎖,是以不會導緻死鎖現象發生;而Lock在發生異常時,如果沒有主動通過unLock()去釋放鎖,則很可能造成死鎖現象,需要注意的是,在使用Lock時需要在finally塊中釋放鎖;
- Lock可以讓等待鎖的線程響應中斷,synchronized不行,使用synchronized時,等待的線程會一直等待下去,不能夠響應中斷;
- 通過Lock可以知道有沒有成功擷取鎖,synchronized不行。
值得一提的是,Lock有ReadWriteLock支援并發讀。
讀寫鎖将對一個資源的通路分成了兩個鎖,一個ReadLock讀鎖和一個WriteLock寫鎖。正因為有了讀寫鎖,Lock才做到了多個線程之間的讀操作不會發生沖突。
ReadWriteLock
上面隻是對synchronized與Lock兩者差別簡單的對比,面試時,面試官問這樣的問題,synchronized與Lock有什麼差別,我想主要是考察求職者對線程并發基礎能力的掌握。
在實際應用中,線程以及線程安全性是非常重要,對于這部分内容了解不夠深入,而又需要用到生産項目中,遇到問題時很難定位到問題,容易造成損失。
對于一些常見的知識點,面試前建議多複習下。
由于筆者知識及水準有限,文中錯漏之處在所難免,如有不足之處,歡迎交流。