最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多線程并發(fā)編程和鎖原理解析

 更新時間:2019年12月23日 14:08:17   作者:1024。  
這篇文章主要介紹了Java多線程并發(fā)編程和鎖原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

這篇文章主要介紹了Java多線程并發(fā)編程和鎖原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

一.前言

  最近項目遇到多線程并發(fā)的情景(并發(fā)搶單&恢復(fù)庫存并行),代碼在正常情況下運行沒有什么問題,在高并發(fā)壓測下會出現(xiàn):庫存超發(fā)/總庫存與sku庫存對不上等各種問題。

  在運用了 限流/加鎖等方案后,問題得到解決。

  加鎖方案見下文。

二.樂觀鎖 & 悲觀鎖

  1.樂觀鎖

   顧名思義,就是很樂觀,每次去拿數(shù)據(jù)的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù),可以使用版本號(version)等機制。

   例如:mybatis-plus 自帶插件OptimisticLockerInterceptor,在數(shù)據(jù)庫表加上一個version字段,每次更新完數(shù)據(jù)庫mp會自動在version字段上加1,如果在更新提交的時候發(fā)現(xiàn)version字段的值與數(shù)據(jù)庫中最新的值不一致,則提交失敗。

  2.悲觀鎖

   悲觀鎖總是假設(shè)會出現(xiàn)最壞的情況,每次去拿數(shù)據(jù)的時候都認為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會阻塞直到它拿到鎖。

   傳統(tǒng)的MySQL關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。

   Java的同步synchronized關(guān)鍵字的實現(xiàn)就是典型的悲觀鎖。

  3.總結(jié)

   悲觀鎖適合寫操作多的場景,先加鎖可以保證寫操作時數(shù)據(jù)正確。

   樂觀鎖適合讀操作多的場景,不加鎖的特點能夠使其讀操作的性能大幅提升。

三.獨占鎖 & 共享鎖

  1.獨占鎖

    是指該鎖一次只能被一個線程所持有。

    例如:Synchronized 和 ReentrantLock ,它們同時也是悲觀鎖

   2.共享鎖

    是指該鎖可被多個線程所持有,允許多個線程同時去獲取。

    例如:Semaphore 和 ReadWriteLock 和 countdownlatch,其讀鎖是共享鎖,寫鎖是獨享鎖。

   3.總結(jié)

    讀鎖的共享鎖可保證并發(fā)讀是非常高效的,讀寫,寫讀 ,寫寫的過程是互斥的。

     獨享鎖與共享鎖也是通過AQS來實現(xiàn)的,通過實現(xiàn)不同的方法,來實現(xiàn)獨享或者共享。

四.公平鎖 & 非公平鎖

  1.公平鎖

   加鎖前先查看是否有排隊等待的線程,有的話優(yōu)先處理排在前面的線程,先來先得。

  2.非公平鎖

   線程加鎖時直接嘗試獲取鎖,獲取不到就自動到隊尾等待。

  3.總結(jié)

   更多的是直接使用非公平鎖:非公平鎖比公平鎖性能高5-10倍,因為公平鎖需要在多核情況下維護一個隊列,如果當前線程不是隊列的第一個無法獲取鎖,增加了線程切換次數(shù)。

五.java線程鎖

  由于多個線程是共同占有所屬進程的資源和地址空間的,那么就會存在一個問題:如果多個線程要同時訪問某個資源,怎么處理?

  在Java并發(fā)編程中,經(jīng)常遇到多個線程訪問同一個共享資源 ,這時候作為開發(fā)者必須考慮如何維護數(shù)據(jù)一致性,這就是Java鎖機制(同步問題)的來源。

  Java提供了多種多線程鎖機制的實現(xiàn)方式,常見的有:

  •   synchronized
  •   ReentrantLock
  •   Semaphore
  •   AtomicInteger等

    每種機制都有優(yōu)缺點與各自的適用場景,必須熟練掌握他們的特點才能在Java多線程應(yīng)用開發(fā)時得心應(yīng)手。

  1.Synchronized

  在Java中synchronized關(guān)鍵字被常用于維護數(shù)據(jù)一致性。synchronized機制是給共享資源上鎖,只有拿到鎖的線程才可以訪問共享資源,這樣就可以強制使得對共享資源的訪問都是順序的。

   Java開發(fā)人員都認識synchronized,使用它來實現(xiàn)多線程的同步操作是非常簡單的,只要在需要同步的對方的方法、類或代碼塊中加入該關(guān)鍵字,它能夠保證在同一個時刻最多只有一個線程執(zhí)行同一個對象的同步代碼,可保證修飾的代碼在執(zhí)行過程中不會被其他線程干擾。使用synchronized修飾的代碼具有原子性和可見性,在需要進程同步的程序中使用的頻率非常高,可以滿足一般的進程同步要求?! ?/p>

 synchronized (obj) {
    //方法
    …….
  }

synchronized實現(xiàn)的機理依賴于軟件層面上的JVM,因此其性能會隨著Java版本的不斷升級而提高。

到了Java1.6,synchronized進行了很多的優(yōu)化,有適應(yīng)自旋、鎖消除、鎖粗化、輕量級鎖及偏向鎖等,效率有了本質(zhì)上的提高。在之后推出的Java1.7與1.8中,均對該關(guān)鍵字的實現(xiàn)機理做了優(yōu)化。

需要說明的是,當線程通過synchronized等待鎖時是不能被Thread.interrupt()中斷的,因此程序設(shè)計時必須檢查確保合理,否則可能會造成線程死鎖的尷尬境地。

最后,盡管Java實現(xiàn)的鎖機制有很多種,并且有些鎖機制性能也比synchronized高,但還是強烈推薦在多線程應(yīng)用程序中使用該關(guān)鍵字,因為實現(xiàn)方便,后續(xù)工作由JVM來完成,可靠性高。只有在確定鎖機制是當前多線程程序的性能瓶頸時,才考慮使用其他機制,如ReentrantLock等。

總結(jié):在資源競爭不是很激烈的情況下,偶爾會有同步的情形下,synchronized是很合適的。原因在于,編譯程序通常會盡可能的進行優(yōu)化synchronize,另外可讀性非常好。

2.ReentrantLock

  可重入鎖,顧名思義,這個鎖可以被線程多次重復(fù)進入進行獲取操作。

  ReentantLock繼承接口Lock并實現(xiàn)了接口中定義的方法,除了能完成synchronized所能完成的所有工作外,還提供了諸如可響應(yīng)中斷鎖、可輪詢鎖請求、定時鎖等避免多線程死鎖的法。

  Lock實現(xiàn)的機理依賴于特殊的CPU指定,可以認為不受JVM的約束,并可以通過其他語言平臺來完成底層的實現(xiàn)。在并發(fā)量較小的多線程應(yīng)用程序中,ReentrantLock與synchronized性能相差無幾,但在高并發(fā)量的條件下,synchronized性能會迅速下降幾十倍,而ReentrantLock的性能卻能依然維持一個水準。

  因此我們建議在高并發(fā)量情況下使用ReentrantLock。

  ReentrantLock引入兩個概念:公平鎖與非公平鎖。

  公平鎖指的是鎖的分配機制是公平的,通常先對鎖提出獲取請求的線程會先被分配到鎖。反之,JVM按隨機、就近原則分配鎖的機制則稱為不公平鎖。

  ReentrantLock在構(gòu)造函數(shù)中提供了是否公平鎖的初始化方式,默認為非公平鎖。這是因為,非公平鎖實際執(zhí)行的效率要遠遠超出公平鎖,除非程序有特殊需要,否則最常用非公平鎖的分配機制。

  ReentrantLock通過方法lock()與unlock()來進行加鎖與解鎖操作,與synchronized會被JVM自動解鎖機制不同,ReentrantLock加鎖后需要手動進行解鎖。為了避免程序出現(xiàn)異常而無法正常解鎖的情況,使用ReentrantLock必須在finally控制塊中進行解鎖操作。通常使用方式如下所示:

/**
 * 初始化一個非公平鎖(該鎖只適用于單實例)
 */
private static Lock lock = new ReentrantLock(false);

void test() {
  try {  
   lock.lock();
   //...執(zhí)行業(yè)務(wù)邏輯
  }finally {
   lock.unlock();
  } 
}

總結(jié):在資源競爭不激烈的情形下,性能稍微比synchronized差點點。但是當同步非常激烈的時候,synchronized的性能一下子能下降好幾十倍,而ReentrantLock確還能維持常態(tài)。高并發(fā)量情況下使用ReentrantLock。

注意:Spring注解和同步鎖不能同步問題解決

3.Semaphore (信號量)

  上述兩種鎖機制類型都是“互斥鎖”,互斥是進程同步關(guān)系的一種特殊情況,相當于只存在一個臨界資源,因此同時最多只能給一個線程提供服務(wù)。但是,在實際復(fù)雜的多線程應(yīng)用程序中,可能存在多個臨界資源,這時候我們可以借助Semaphore信號量來完成多個臨界資源的訪問。

  Semaphore基本能完成ReentrantLock的所有工作,使用方法也與之類似,通過acquire()與release()方法來獲得和釋放臨界資源。

  經(jīng)實測,Semaphone.acquire()方法默認為可響應(yīng)中斷鎖,與ReentrantLock.lockInterruptibly()作用效果一致,也就是說在等待臨界資源的過程中可以被Thread.interrupt()方法中斷。

  此外,Semaphore也實現(xiàn)了可輪詢的鎖請求與定時鎖的功能,除了方法名tryAcquire與tryLock不同,其使用方法與ReentrantLock幾乎一致。Semaphore也提供了公平與非公平鎖的機制,也可在構(gòu)造函數(shù)中進行設(shè)定。

  Semaphore的鎖釋放操作也由手動進行,因此與ReentrantLock一樣,為避免線程因拋出異常而無法正常釋放鎖的情況發(fā)生,釋放鎖的操作也必須在finally代碼塊中完成。

/** 定義一個非公平的共享鎖 */
public static Semaphore LOCK = new Semaphore(5, false);

void test() {
  try{
   //獲取許可
   LOCK.acquire();
  } 
  finally {
   //釋放許可
   LOCK.release();
  }
}

  總結(jié):Semaphore有著非常強大的功能,并且是共享鎖,在特殊情景時非常有效。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • myBatis實現(xiàn)三級嵌套復(fù)雜對象的賦值問題

    myBatis實現(xiàn)三級嵌套復(fù)雜對象的賦值問題

    這篇文章主要介紹了myBatis實現(xiàn)三級嵌套復(fù)雜對象的賦值問題,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • RocketMQ設(shè)計之主從復(fù)制和讀寫分離

    RocketMQ設(shè)計之主從復(fù)制和讀寫分離

    這篇文章主要介紹了RocketMQ設(shè)計之主從復(fù)制和讀寫分離,RocketMQ提高消費避免Broker發(fā)生單點故障引起B(yǎng)roker上的消息無法及時消費,下文關(guān)于了RocketMQ的相關(guān)內(nèi)容,需要的小伙伴可以參考一下
    2022-03-03
  • 詳解快速排序算法中的區(qū)間劃分法及Java實現(xiàn)示例

    詳解快速排序算法中的區(qū)間劃分法及Java實現(xiàn)示例

    這篇文章主要介紹了詳解快速排序算法中的區(qū)間劃分法及Java實現(xiàn)示例,文中分別介紹了快排時兩種區(qū)間劃分的思路,需要的朋友可以參考下
    2016-04-04
  • maven項目pom.xml中parent標簽的使用小結(jié)

    maven項目pom.xml中parent標簽的使用小結(jié)

    使用maven是為了更好的幫項目管理包依賴,maven的核心就是pom.xml,當我們需要引入一個jar包時,在pom文件中加上就可以從倉庫中依賴到相應(yīng)的jar包,本文就來介紹一下maven項目pom.xml中parent標簽的使用小結(jié),感興趣的可以了解一下
    2023-12-12
  • 詳解Springboot事務(wù)管理

    詳解Springboot事務(wù)管理

    本篇文章主要介紹了詳解Springboot事務(wù)管理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • Java多個線程同時執(zhí)行的方法

    Java多個線程同時執(zhí)行的方法

    這篇文章主要介紹了Java多線程處理文件詳解與代碼示例,通過本文的介紹和代碼示例,我們了解了如何使用Java多線程來處理文件,使用多線程技術(shù)可以顯著提高文件處理的效率,特別是對于大量文件的處理任務(wù),需要的朋友可以參考下
    2024-12-12
  • Java的函數(shù)式編程詳解

    Java的函數(shù)式編程詳解

    用了這么久的Java8,我尋思這種話也好意思說出來嗎,難道自己是PythonBoy出身就是看不懂Java的理由嗎,身為一個合格的后端Boy不會還有人看不明白Java的函數(shù)式編程吧,接下來小編和大家淺聊一下Java的函數(shù)式編程,需要的朋友可以參考下
    2023-10-10
  • bug解決Failed_to_execute_goal_org.springframework

    bug解決Failed_to_execute_goal_org.springframework

    這篇文章主要為大家介紹了bug解決Failed_to_execute_goal_org.springframework,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • Java線程的生命周期和狀態(tài)控制_動力節(jié)點Java學(xué)院整理

    Java線程的生命周期和狀態(tài)控制_動力節(jié)點Java學(xué)院整理

    這篇文章主要介紹了Java線程的生命周期和狀態(tài)控制,需要的朋友可以參考下
    2017-05-05
  • springSecurity+jwt使用小結(jié)

    springSecurity+jwt使用小結(jié)

    本文介紹了使用Spring Security與JWT進行身份驗證和授權(quán),實現(xiàn)用戶認證和授權(quán)的詳細流程,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11

最新評論

达州市| 揭东县| 邻水| 来安县| 高清| 启东市| 华亭县| 文水县| 夏邑县| 鄢陵县| 邓州市| 延津县| 茂名市| 宝丰县| 迭部县| 宁夏| 随州市| 潮州市| 井研县| 炎陵县| 恭城| 信丰县| 吴桥县| 定日县| 遵义市| 沛县| 久治县| 天门市| 门头沟区| 新平| 泾源县| 松溪县| 丹巴县| 泗水县| 盈江县| 长岭县| 光山县| 黄石市| 雅江县| 克拉玛依市| 慈利县|