分布式鎖正確打開方式 程序怎樣實(shí)現(xiàn)死鎖?該如何分析死鎖?
程序怎樣實(shí)現(xiàn)死鎖?該如何分析死鎖?所謂死鎖:是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過程中因?yàn)闋?zhēng)奪資源而相互等待的現(xiàn)象。如果沒有外力,他們就無法前進(jìn)。此時(shí),系統(tǒng)被稱為處于死鎖狀態(tài)或系統(tǒng)有死鎖。這些總是互相等待的
程序怎樣實(shí)現(xiàn)死鎖?該如何分析死鎖?
所謂死鎖:是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過程中因?yàn)闋?zhēng)奪資源而相互等待的現(xiàn)象。如果沒有外力,他們就無法前進(jìn)。此時(shí),系統(tǒng)被稱為處于死鎖狀態(tài)或系統(tǒng)有死鎖。這些總是互相等待的進(jìn)程稱為死鎖進(jìn)程。由于資源的占用是互斥的,當(dāng)一個(gè)進(jìn)程申請(qǐng)資源時(shí),如果沒有外力的協(xié)助,相關(guān)進(jìn)程永遠(yuǎn)無法分配到必要的資源,這就產(chǎn)生了一種特殊的死鎖現(xiàn)象。
雖然在運(yùn)行過程中可能會(huì)出現(xiàn)死鎖,但必須滿足一定的條件,死鎖必須滿足以下四個(gè)必要條件。
1)互斥情況:指一個(gè)進(jìn)程獨(dú)占使用分配的資源,即一段時(shí)間內(nèi)一個(gè)資源只被一個(gè)進(jìn)程占用。如果此時(shí)有其他進(jìn)程請(qǐng)求資源,請(qǐng)求者只能等待,直到占用資源的進(jìn)程用完釋放。
2)請(qǐng)求和保持條件:指已經(jīng)保持了至少一個(gè)資源的進(jìn)程,但是提出了新的資源請(qǐng)求,并且這個(gè)資源已經(jīng)被其他進(jìn)程占用。此時(shí),請(qǐng)求進(jìn)程被阻塞,但是它仍然持有它已經(jīng)獲得的其他資源。
3)非剝奪條件:指進(jìn)程獲得的資源,在用完之前不能被剝奪,用完之后才能自行釋放。
4)循環(huán)等待條件:發(fā)生死鎖時(shí),必須有一個(gè)進(jìn)程——一個(gè)環(huán)形的資源鏈,即進(jìn)程集{P0,P1,P2,..,Pn}正在等待P1占用的一個(gè)資源;P1正在等待被P2占領(lǐng)的資源,...,并且Pn正在等待已經(jīng)被P0占用的資源。
系統(tǒng)發(fā)生死鎖后,應(yīng)及時(shí)檢測(cè)并采取適當(dāng)措施解除死鎖。目前,處理死鎖的方法可以歸納為以下四種
1)防止死鎖
這是一種比較簡(jiǎn)單直觀的提前預(yù)防方法。方法是設(shè)置一些限制來破壞死鎖的四個(gè)必要條件中的一個(gè)或多個(gè),從而防止死鎖。死鎖預(yù)防是一種易于實(shí)現(xiàn)的方法,已被廣泛使用。然而,所施加的限制往往過于嚴(yán)格,這可能導(dǎo)致系統(tǒng)資源利用率和系統(tǒng)吞吐量的降低。
2)避免死鎖
這種方法也是一種預(yù)防策略,但不需要事先采取各種限制性措施來破壞死鎖的四個(gè)必要條件,而是在動(dòng)態(tài)分配資源的過程中使用一些方法來防止系統(tǒng)進(jìn)入不安全狀態(tài),從而避免死鎖。
3)檢測(cè)死鎖
這種方法不需要事先采取任何限制措施,也不需要檢查系統(tǒng)是否進(jìn)入了不安全區(qū)。這種方法允許系統(tǒng)在操作過程中出現(xiàn)死鎖。但是,通過系統(tǒng)設(shè)置的檢測(cè)機(jī)制,可以及時(shí)檢測(cè)到死鎖的發(fā)生,并準(zhǔn)確地確定與死鎖相關(guān)的進(jìn)程和資源,然后采取適當(dāng)?shù)拇胧南到y(tǒng)中清除已經(jīng)發(fā)生的死鎖。
4)消除僵局
這與檢測(cè)死鎖是兼容的。測(cè)度集。當(dāng)在系統(tǒng)中檢測(cè)到死鎖時(shí),進(jìn)程必須從死鎖狀態(tài)中釋放出來。常見的實(shí)現(xiàn)方法是取消或掛起一些進(jìn)程,以便回收一些資源,然后將這些資源分配給已經(jīng)處于阻塞狀態(tài)的進(jìn)程,使其做好繼續(xù)運(yùn)行的準(zhǔn)備。死鎖檢測(cè)和消除措施可以使系統(tǒng)獲得更好的資源利用率和吞吐量,但也是最難實(shí)現(xiàn)的。
悲觀鎖:假設(shè)將發(fā)生并發(fā),所有可能違反數(shù)據(jù)完整性的操作都將被屏蔽。
樂觀鎖定:假設(shè)不會(huì)發(fā)生并發(fā),我們只會(huì)在提交操作時(shí)檢查是否違反了數(shù)據(jù)完整性。樂觀鎖定可以 解決不了骯臟閱讀的問題。
悲觀鎖,顧名思義就是悲觀。每次獲取數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次獲取數(shù)據(jù)的時(shí)候都會(huì)加鎖,這樣別人就會(huì)屏蔽它,直到它得到鎖。傳統(tǒng)的關(guān)系數(shù)據(jù)庫(kù)中使用了許多這樣的鎖機(jī)制,如行鎖、表鎖、讀鎖、寫鎖等。,操作前全部鎖定。
樂觀鎖,顧名思義,就是樂觀。每次去取數(shù)據(jù),他都認(rèn)為別人不會(huì)修改,所以他贏了 不要鎖。但是在更新的時(shí)候,他會(huì)判斷這段時(shí)間別人有沒有更新過數(shù)據(jù),他可以使用版本號(hào)等機(jī)制。樂觀鎖定適用于多讀應(yīng)用程序類型,可以提高吞吐量。例如,如果數(shù)據(jù)庫(kù)提供類似write_condition的機(jī)制,它實(shí)際上提供了樂觀鎖定。
我的頭條號(hào)有更多關(guān)于發(fā)行、網(wǎng)站、開發(fā)語言等視頻。你可以看看。
如何保證同一資源被多個(gè)線程并發(fā)訪問時(shí)的完整性?
對(duì)于這個(gè)問題,我們首先想到的是使用synchronized關(guān)鍵字,這是一個(gè)解決方案,比如:
公共同步void setStatus(布爾b) {}
但是synchronized不適合高并發(fā)數(shù)據(jù),會(huì)導(dǎo)致程序特別慢,不適合集群,負(fù)載均衡后數(shù)據(jù)會(huì)有問題。
我們使用另一種解決方案,redis分布式鎖。redis是單線程服務(wù),高效的鍵/值結(jié)構(gòu),支持高可用的分布式集群,可以讓多臺(tái)機(jī)器上的多個(gè)進(jìn)程互斥相同的數(shù)據(jù)。
讓 讓我們談?wù)剅edis從創(chuàng)建到使用的過程:
1.使用maven下載redis所依賴的包,在pom.xml中進(jìn)行配置:
ltdependencygt ltartifactidgt spring-boot-starter-data-redi SLT/artifactIdgt
2.熟悉r:在設(shè)置新值之前獲取以前的值。
3、新增redis類寫鎖,解鎖方法:
redis的自動(dòng)注入
@自動(dòng)連線
私有字符串模板
/***
*鎖定
* @param密鑰id
* @param value當(dāng)前時(shí)間超時(shí)
* @return*/
命令對(duì)應(yīng)的公共布爾鎖(String Key,String Value) {//setnx。
//可以設(shè)置值返回true,但是可以 不要將該值設(shè)置為返回false。
if(redisTemplate.opsForValue()。setIfAbsent(key,value)) { return true }
//確保只有一個(gè)線程獲得鎖。
字符串current value redis template . ops for value()。獲取(鍵)
//如果鎖過期,則存儲(chǔ)的鎖小于當(dāng)前時(shí)間。
如果(!(當(dāng)前值)ampamp(當(dāng)前值)lt ()) {
//獲取最后一次鎖定的時(shí)間
string old value redis template . opsforvalue()。getAndSet(鍵,值)
如果(!(old value)amp old value . equals(current value)){ return true } } return false }
/**
*解鎖
*/public void unlock(字符串鍵,字符串值){
嘗試{
字符串current value redis template . ops for value()。get(key) if(!(當(dāng)前值)ampamp當(dāng)前值. equals(值)){
值()的Redisttemplate.ops。getOperations()。delete(key)} Catch(Exception e){([Redis分布式鎖]解鎖異常,{}