日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

java并发排它锁_Java并发编程进阶——锁(解析)

發(fā)布時(shí)間:2023/12/15 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java并发排它锁_Java并发编程进阶——锁(解析) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、鎖是什么

java開發(fā)中進(jìn)行并發(fā)編程時(shí)針對操作同一塊區(qū)域時(shí),如果不加鎖會(huì)出現(xiàn)并發(fā)問題,數(shù)據(jù)不是自己預(yù)計(jì)得到的值。我覺得有點(diǎn)像mysql事務(wù)中臟讀、不可重復(fù)讀、幻讀的問題。加鎖的目的是為了保證同一時(shí)間只有我一個(gè)人操作同一個(gè)資源。

二、如何在代碼里面加鎖

jdk提供給了我們很多鎖的實(shí)現(xiàn)方式,用于各種情況鎖的使用:

  • 使用synchronized修飾方法、修飾代碼塊等;
  • 使用ReentrantLock來獲取鎖;
  • ReadWriteLock讀寫分開的讀寫鎖;
  • ReentrantReadWriteLock;
  • 三、這些鎖有什么區(qū)別

    Ⅰ、實(shí)現(xiàn)原理不同

    synchronized是鎖實(shí)現(xiàn)原理是jdk實(shí)現(xiàn)的:

    public class SynchronizedDemo {public static void main(String[] args) {Object o = new Object();synchronized (o){System.out.println("ReentrantLockDemo");}} }

    使用synchronized修飾的代碼會(huì)在編譯時(shí)加上monitorenter、monitorexit進(jìn)行修飾,那么問題來了,為什么用這個(gè)修飾后就能夠保證線程執(zhí)行過程中的安全呢?
    因?yàn)閖dk在執(zhí)行monitorenter、monitorexit區(qū)塊的時(shí)候是保證原子性的,要么執(zhí)行完成要么執(zhí)行不完成。synchronized修飾的代碼塊有可視性、原子性、順序性(防止重排序)。

    ReentrantLock是怎么實(shí)現(xiàn)鎖的機(jī)制呢?

    通過繼承AbstractQueuedLongSynchronizer(AQS)來進(jìn)行鎖的,實(shí)現(xiàn)原理是AQS中有一個(gè)變量來控制是否獲取到了鎖,通過Unsafe的CAS操作來獲取鎖,從而保證線程安全。

    那么問題來了?CAS操作的ABA問題如何解決?

    concurrent包中有提供AtomicStampedReference來解決ABA問題,也就是在CAS操作的同時(shí)需要再增加版本的判斷,從而保證不出現(xiàn)ABA的問題。

    public class SolveCAS {// 主內(nèi)存共享變量,初始值為1,版本號為1private static AtomicStampedReference<Integer> atomicStampedReference = newAtomicStampedReference<>(1, 1);public static void main(String[] args) {// t1,期望將1改為10new Thread(() -> {// 第一次拿到的時(shí)間戳int stamp = atomicStampedReference.getStamp();System.out.println(Thread.currentThread().getName()+" 第1次時(shí)間戳:"+stamp+" 值為:"+atomicStampedReference.getReference());// 休眠5s,確保t2執(zhí)行完ABA操作try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }// t2將時(shí)間戳改為了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()+" 當(dāng)前最新時(shí)間戳:"+atomicStampedReference.getStamp()+" 最新值為:"+atomicStampedReference.getReference());},"t1").start();// t2進(jìn)行ABA操作new Thread(() -> {// 第一次拿到的時(shí)間戳int stamp = atomicStampedReference.getStamp();System.out.println(Thread.currentThread().getName()+" 第1次時(shí)間戳:"+stamp+" 值為:"+atomicStampedReference.getReference());// 休眠,修改前確保t1也拿到同樣的副本,初始值為1try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }// 將副本改為20,再寫入,緊接著又改為1,寫入,每次提升一個(gè)時(shí)間戳,中間t1沒介入atomicStampedReference.compareAndSet(1, 20, stamp, stamp + 1);System.out.println(Thread.currentThread().getName()+" 第2次時(shí)間戳:"+atomicStampedReference.getStamp()+" 值為:"+atomicStampedReference.getReference());atomicStampedReference.compareAndSet(20, 1, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);System.out.println(Thread.currentThread().getName()+" 第3次時(shí)間戳:"+atomicStampedReference.getStamp()+" 值為:"+atomicStampedReference.getReference());},"t2").start();} }

    Ⅱ、使用場景不同

    ReadWriteLock可以使用在讀多寫少的情況,盡量提升并發(fā)的能力 ReadWriteLock、synchronized使用的是獨(dú)占鎖,但是jdk對synchronized在編譯時(shí)會(huì)有優(yōu)化。

    更多關(guān)于Java的技術(shù)和資訊可以關(guān)注我的專欄:

    Java架構(gòu)筑基?zhuanlan.zhihu.com

    專欄免費(fèi)給大家分享Java架構(gòu)的學(xué)習(xí)資料和視頻

    總結(jié)

    以上是生活随笔為你收集整理的java并发排它锁_Java并发编程进阶——锁(解析)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。