摘要:在包中已經(jīng)包含了讀寫鎖樂觀鎖總是認(rèn)為不會產(chǎn)生并發(fā)問題,每次去取數(shù)據(jù)的時候總認(rèn)為不會有其他線程對數(shù)據(jù)進行修改,因此不會上鎖,但是在更新時會判斷其他線程在這之前有沒有對數(shù)據(jù)進行修改,一般會使用版本號機制或操作實現(xiàn)。
重入鎖
鎖作為并發(fā)共享數(shù)據(jù),保證一致性的工具,在JAVA平臺有多種實現(xiàn)(如 synchronized(重量級) 和 ReentrantLock(輕量級)等等 ) 。這些已經(jīng)寫好提供的鎖為我們開發(fā)提供了便利。
重入鎖,也叫做遞歸鎖,指的是同一線程 外層函數(shù)獲得鎖之后 ,內(nèi)層遞歸函數(shù)仍然有獲取該鎖的代碼,但不受影響。
在JAVA環(huán)境下 ReentrantLock 和synchronized 都是 可重入鎖
相比Java中的鎖(Locks in Java)里L(fēng)ock實現(xiàn),讀寫鎖更復(fù)雜一些。假設(shè)你的程序中涉及到對一些共享資源的讀和寫操作,且寫操作沒有讀操作那么頻繁。在沒有寫操作的時候,兩個線程同時讀一個資源沒有任何問題,所以應(yīng)該允許多個線程能在同時讀取共享資源。但是如果有一個線程想去寫這些共享資源,就不應(yīng)該再有其它線程對該資源進行讀或?qū)懀ㄗg者注:也就是說:讀-讀能共存,讀-寫不能共存,寫-寫不能共存)。這就需要一個讀/寫鎖來解決這個問題。Java5在java.util.concurrent包中已經(jīng)包含了讀寫鎖(ReentrantReadWriteLock)
樂觀鎖總是認(rèn)為不會產(chǎn)生并發(fā)問題,每次去取數(shù)據(jù)的時候總認(rèn)為不會有其他線程對數(shù)據(jù)進行修改,因此不會上鎖,但是在更新時會判斷其他線程在這之前有沒有對數(shù)據(jù)進行修改,一般會使用版本號機制或CAS操作實現(xiàn)。
version方式:一般是在數(shù)據(jù)表中加上一個數(shù)據(jù)版本號version字段,表示數(shù)據(jù)被修改的次數(shù),當(dāng)數(shù)據(jù)被修改時,version值會加一。當(dāng)線程A要更新數(shù)據(jù)值時,在讀取數(shù)據(jù)的同時也會讀取version值,在提交更新時,若剛才讀取到的version值為當(dāng)前數(shù)據(jù)庫中的version值相等時才更新,否則重試更新操作,直到更新成功。
核心SQL語句
update table set x=x+1, version=version+1 where id=#{id} and version=#{version};
CAS操作方式:即compare and swap 或者 compare and set,涉及到三個操作數(shù),數(shù)據(jù)所在的內(nèi)存值,預(yù)期值,新值。當(dāng)需要更新時,判斷當(dāng)前內(nèi)存值與之前取到的值是否相等,若相等,則用新值更新,若失敗則重試,一般情況下是一個自旋操作,即不斷的重試。
悲觀鎖總是假設(shè)最壞的情況,每次取數(shù)據(jù)時都認(rèn)為其他線程會修改,所以都會加鎖(讀鎖、寫鎖、行鎖等),當(dāng)其他線程想要訪問數(shù)據(jù)時,都需要阻塞掛起??梢砸揽繑?shù)據(jù)庫實現(xiàn),如行鎖、讀鎖和寫鎖等,都是在操作之前加鎖,在Java中,synchronized的思想也是悲觀鎖。
原子類java.util.concurrent.atomic包:原子類的小工具包,支持在單個變量上解除鎖的線程安全編程
原子變量類相當(dāng)于一種泛化的 volatile 變量,能夠支持原子的和有條件的讀-改-寫操作。AtomicInteger 表示一個int類型的值,并提供了 get 和 set 方法,這些 Volatile 類型的int變量在讀取和寫入上有著相同的內(nèi)存語義。它還提供了一個原子的 compareAndSet 方法(如果該方法成功執(zhí)行,那么將實現(xiàn)與讀取/寫入一個 volatile 變量相同的內(nèi)存效果),以及原子的添加、遞增和遞減等方法。AtomicInteger 表面上非常像一個擴展的 Counter 類,但在發(fā)生競爭的情況下能提供更高的可伸縮性,因為它直接利用了硬件對并發(fā)的支持。
CAS:Compare and Swap,即比較再交換。
jdk5增加了并發(fā)包java.util.concurrent.*,其下面的類使用CAS算法實現(xiàn)了區(qū)別于synchronouse同步鎖的一種樂觀鎖。JDK 5之前Java語言是靠synchronized關(guān)鍵字保證同步的,這是一種獨占鎖,也是是悲觀鎖。
常用:
AtomicBoolean
AtomicInteger
AtomicLong
AtomicReference
如果想在不同的jvm中保證數(shù)據(jù)同步,使用分布式鎖技術(shù)。有數(shù)據(jù)庫實現(xiàn)、緩存實現(xiàn)、Zookeeper分布式鎖
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/74738.html
摘要:底層是是通過對象,對象有自己的對象頭,存儲了很多信息,其中一個信息標(biāo)示是被哪個線程持有。當(dāng)一個線程執(zhí)行的代碼出現(xiàn)異常時,其所持有的鎖會自動釋放。 前言 回顧前面: 多線程三分鐘就可以入個門了! Thread源碼剖析 多線程基礎(chǔ)必要知識點!看了學(xué)習(xí)多線程事半功倍 只有光頭才能變強! 本文章主要講的是Java多線程加鎖機制,有兩種: Synchronized 顯式Lock 不得不嘮...
摘要:當(dāng)一個線程持有重量級鎖時,另外一個線程就會被直接踢到同步隊列中等待。 java代碼先編譯成字節(jié)碼,字節(jié)碼最后編譯成cpu指令,因此Java的多線程實現(xiàn)最終依賴于jvm和cpu的實現(xiàn) synchronized和volatile 我們先來討論一下volatile關(guān)鍵字的作用以及實現(xiàn)機制,每個線程看到的用volatile修飾的變量的值都是最新的,更深入的解釋就涉及到Java的內(nèi)存模型了,我們...
摘要:并發(fā)機制與底層實現(xiàn)原理是輕量級的它在多處理器開發(fā)中保證了共享變量的可見性,因為它不會引起線程上下文的切換和調(diào)度,所以比的使用和執(zhí)行成本更底。如果線程間存在鎖競爭,會帶來額外的鎖撤銷的消耗。輕量級鎖競爭的線程不會阻塞,提高了程序的響應(yīng)速度。 java并發(fā)機制與底層實現(xiàn)原理 volatile volatile是輕量級的synchronize,它在多處理器開發(fā)中保證了共享變量的可見性,因為它...
摘要:在這個等待通知機制中,我們需要考慮以下四個要素。何時等待線程要求的條件不滿足就等待。是會隨機地通知等待隊列中的一個線程,而會通知等待隊列中的所有線程。 由上一篇文章你應(yīng)該已經(jīng)知道,在 破壞占用且等待條件 的時候,如果轉(zhuǎn)出賬本和轉(zhuǎn)入賬本不滿足同時在文件架上這個條件,就用死循環(huán)的方式來循環(huán)等待,核心代碼如下: // 一次性申請轉(zhuǎn)出賬戶和轉(zhuǎn)入賬戶,直到成功 while(!actr.apply...
閱讀 3754·2021-09-22 15:34
閱讀 1248·2019-08-29 17:25
閱讀 3464·2019-08-29 11:18
閱讀 1450·2019-08-26 17:15
閱讀 1800·2019-08-23 17:19
閱讀 1293·2019-08-23 16:15
閱讀 772·2019-08-23 16:02
閱讀 1395·2019-08-23 15:19