真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java:既然有了synchronized,為什么還要提供Lock?

摘要:在Java中提供了synchronized關(guān)鍵字來保證只有一個線程能夠訪問同步代碼塊。既然已經(jīng)提供了synchronized關(guān)鍵字,那為何在Java的SDK包中,還會提供Lock接口呢?這是不是重復(fù)造輪子,多此一舉呢?

本文分享自華為云社區(qū)《【高并發(fā)】Java中提供了synchronized,為什么還要提供Lock呢?》,作者: 冰 河。

創(chuàng)新互聯(lián)長期為近千家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為措美企業(yè)提供專業(yè)的網(wǎng)站建設(shè)、網(wǎng)站設(shè)計,措美網(wǎng)站改版等技術(shù)服務(wù)。擁有10年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

在Java中提供了synchronized關(guān)鍵字來保證只有一個線程能夠訪問同步代碼塊。既然已經(jīng)提供了synchronized關(guān)鍵字,那為何在Java的SDK包中,還會提供Lock接口呢?這是不是重復(fù)造輪子,多此一舉呢?今天,我們就一起來探討下這個問題。

再造輪子?

既然JVM中提供了synchronized關(guān)鍵字來保證只有一個線程能夠訪問同步代碼塊,為何還要提供Lock接口呢?這是在重復(fù)造輪子嗎?Java的設(shè)計者們?yōu)楹我@樣做呢?讓我們一起帶著疑問往下看。

為何提供Lock接口?

很多小伙伴可能會聽說過,在Java 1.5版本中,synchronized的性能不如Lock,但在Java 1.6版本之后,synchronized做了很多優(yōu)化,性能提升了不少。那既然synchronized關(guān)鍵字的性能已經(jīng)提升了,那為何還要使用Lock呢?

如果我們向更深層次思考的話,就不難想到了:我們使用synchronized加鎖是無法主動釋放鎖的,這就會涉及到死鎖的問題。

死鎖問題

如果要發(fā)生死鎖,則必須存在以下四個必要條件,四者缺一不可。

  • 互斥條件

在一段時間內(nèi)某資源僅為一個線程所占有。此時若有其他線程請求該資源,則請求線程只能等待。

  • 不可剝奪條件

線程所獲得的資源在未使用完畢之前,不能被其他線程強(qiáng)行奪走,即只能由獲得該資源的線程自己來釋放(只能是主動釋放)。

  • 請求與保持條件

線程已經(jīng)保持了至少一個資源,但又提出了新的資源請求,而該資源已被其他線程占有,此時請求線程被阻塞,但對自己已獲得的資源保持不放。

  • 循環(huán)等待條件

在發(fā)生死鎖時必然存在一個進(jìn)程等待隊列{P1,P2,…,Pn},其中P1等待P2占有的資源,P2等待P3占有的資源,…,Pn等待P1占有的資源,形成一個進(jìn)程等待環(huán)路,環(huán)路中每一個進(jìn)程所占有的資源同時被另一個申請,也就是前一個進(jìn)程占有后一個進(jìn)程所深情地資源。

synchronized的局限性

如果我們的程序使用synchronized關(guān)鍵字發(fā)生了死鎖時,synchronized關(guān)鍵是是無法破壞“不可剝奪”這個死鎖的條件的。這是因為synchronized申請資源的時候, 如果申請不到, 線程直接進(jìn)入阻塞狀態(tài)了, 而線程進(jìn)入阻塞狀態(tài), 啥都干不了, 也釋放不了線程已經(jīng)占有的資源。

然而,在大部分場景下,我們都是希望“不可剝奪”這個條件能夠被破壞。也就是說對于“不可剝奪”這個條件,占用部分資源的線程進(jìn)一步申請其他資源時, 如果申請不到, 可以主動釋放它占有的資源, 這樣不可剝奪這個條件就破壞掉了。

如果我們自己重新設(shè)計鎖來解決synchronized的問題,我們該如何設(shè)計呢?

解決問題

了解了synchronized的局限性之后,如果是讓我們自己實現(xiàn)一把同步鎖,我們該如何設(shè)計呢?也就是說,我們在設(shè)計鎖的時候,要如何解決synchronized的局限性問題呢?這里,我覺得可以從三個方面來思考這個問題。

(1)能夠響應(yīng)中斷。 synchronized的問題是, 持有鎖A后, 如果嘗試獲取鎖B失敗, 那么線程就進(jìn)入阻塞狀態(tài), 一旦發(fā)生死鎖, 就沒有任何機(jī)會來喚醒阻塞的線程。 但如果阻塞狀態(tài)的線程能夠響應(yīng)中斷信號, 也就是說當(dāng)我們給阻塞的線程發(fā)送中斷信號的時候, 能夠喚醒它, 那它就有機(jī)會釋放曾經(jīng)持有的鎖A。 這樣就破壞了不可剝奪條件了。

(2)支持超時。 如果線程在一段時間之內(nèi)沒有獲取到鎖, 不是進(jìn)入阻塞狀態(tài), 而是返回一個錯誤, 那這個線程也有機(jī)會釋放曾經(jīng)持有的鎖。 這樣也能破壞不可剝奪條件。

(3)非阻塞地獲取鎖。 如果嘗試獲取鎖失敗, 并不進(jìn)入阻塞狀態(tài), 而是直接返回, 那這個線程也有機(jī)會釋放曾經(jīng)持有的鎖。 這樣也能破壞不可剝奪條件。

體現(xiàn)在Lock接口上,就是Lock接口提供的三個方法,如下所示。

// 支持中斷的API
void lockInterruptibly() throws InterruptedException;
// 支持超時的API
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// 支持非阻塞獲取鎖的API
boolean tryLock();

分享標(biāo)題:Java:既然有了synchronized,為什么還要提供Lock?
分享鏈接:http://weahome.cn/article/dsojich.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部