java并发排它锁_Java并发编程进阶——锁(解析)
一、鎖是什么
java開發中進行并發編程時針對操作同一塊區域時,如果不加鎖會出現并發問題,數據不是自己預計得到的值。我覺得有點像mysql事務中臟讀、不可重復讀、幻讀的問題。加鎖的目的是為了保證同一時間只有我一個人操作同一個資源。
二、如何在代碼里面加鎖
jdk提供給了我們很多鎖的實現方式,用于各種情況鎖的使用:
三、這些鎖有什么區別
Ⅰ、實現原理不同
synchronized是鎖實現原理是jdk實現的:
public class SynchronizedDemo {public static void main(String[] args) {Object o = new Object();synchronized (o){System.out.println("ReentrantLockDemo");}} }使用synchronized修飾的代碼會在編譯時加上monitorenter、monitorexit進行修飾,那么問題來了,為什么用這個修飾后就能夠保證線程執行過程中的安全呢?
因為jdk在執行monitorenter、monitorexit區塊的時候是保證原子性的,要么執行完成要么執行不完成。synchronized修飾的代碼塊有可視性、原子性、順序性(防止重排序)。
ReentrantLock是怎么實現鎖的機制呢?
通過繼承AbstractQueuedLongSynchronizer(AQS)來進行鎖的,實現原理是AQS中有一個變量來控制是否獲取到了鎖,通過Unsafe的CAS操作來獲取鎖,從而保證線程安全。
那么問題來了?CAS操作的ABA問題如何解決?
concurrent包中有提供AtomicStampedReference來解決ABA問題,也就是在CAS操作的同時需要再增加版本的判斷,從而保證不出現ABA的問題。
public class SolveCAS {// 主內存共享變量,初始值為1,版本號為1private static AtomicStampedReference<Integer> atomicStampedReference = newAtomicStampedReference<>(1, 1);public static void main(String[] args) {// t1,期望將1改為10new Thread(() -> {// 第一次拿到的時間戳int stamp = atomicStampedReference.getStamp();System.out.println(Thread.currentThread().getName()+" 第1次時間戳:"+stamp+" 值為:"+atomicStampedReference.getReference());// 休眠5s,確保t2執行完ABA操作try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }// t2將時間戳改為了3,cas失敗boolean b = atomicStampedReference.compareAndSet(1, 10, stamp, stamp + 1);System.out.println(Thread.currentThread().getName()+" CAS是否成功:"+b);System.out.println(Thread.currentThread().getName()+" 當前最新時間戳:"+atomicStampedReference.getStamp()+" 最新值為:"+atomicStampedReference.getReference());},"t1").start();// t2進行ABA操作new Thread(() -> {// 第一次拿到的時間戳int stamp = atomicStampedReference.getStamp();System.out.println(Thread.currentThread().getName()+" 第1次時間戳:"+stamp+" 值為:"+atomicStampedReference.getReference());// 休眠,修改前確保t1也拿到同樣的副本,初始值為1try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }// 將副本改為20,再寫入,緊接著又改為1,寫入,每次提升一個時間戳,中間t1沒介入atomicStampedReference.compareAndSet(1, 20, stamp, stamp + 1);System.out.println(Thread.currentThread().getName()+" 第2次時間戳:"+atomicStampedReference.getStamp()+" 值為:"+atomicStampedReference.getReference());atomicStampedReference.compareAndSet(20, 1, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);System.out.println(Thread.currentThread().getName()+" 第3次時間戳:"+atomicStampedReference.getStamp()+" 值為:"+atomicStampedReference.getReference());},"t2").start();} }Ⅱ、使用場景不同
ReadWriteLock可以使用在讀多寫少的情況,盡量提升并發的能力 ReadWriteLock、synchronized使用的是獨占鎖,但是jdk對synchronized在編譯時會有優化。
更多關于Java的技術和資訊可以關注我的專欄:
Java架構筑基?zhuanlan.zhihu.com專欄免費給大家分享Java架構的學習資料和視頻
總結
以上是生活随笔為你收集整理的java并发排它锁_Java并发编程进阶——锁(解析)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ddr读时序波形_测试新体验|如何解决D
- 下一篇: java thread_Java(多线