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

Spring Boot2+JPA之悲觀鎖和樂觀鎖實戰(zhàn)教程

 更新時間:2021年10月15日 09:42:28   作者:Moshow鄭鍇  
這篇文章主要介紹了Spring Boot2+JPA之悲觀鎖和樂觀鎖實戰(zhàn)教程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

前言

大量的請求,或者同時的操作,容易導(dǎo)致系統(tǒng)在業(yè)務(wù)上發(fā)生并發(fā)的問題. 通常講到并發(fā),解決方案無非就是前端限制重復(fù)提交,后臺進行悲觀鎖或者樂觀鎖限制.

悲觀鎖與并發(fā)

悲觀鎖(Pessimistic Lock),顧名思義,就是很悲觀,每次去拿數(shù)據(jù)的時候都認(rèn)為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會block直到解鎖,可以理解為獨占鎖。在java中synchronized和ReentrantLock重入鎖等鎖就是悲觀鎖,數(shù)據(jù)庫中表鎖、行鎖、讀寫鎖等也是悲觀鎖。

利用SQL的for update解決并發(fā)問題

行鎖就是操作數(shù)據(jù)的時候把這一行數(shù)據(jù)鎖住,其他線程想要讀寫必須等待,但同一個表的其他數(shù)據(jù)還是能被其他線程操作的。只要在需要查詢的sql后面加上for update,就能鎖住查詢的行,特別要注意查詢條件必須要是索引列,如果不是索引就會變成表鎖,把整個表都鎖住。

public interface ArticleRepository extends JpaRepository<Article, Long> {
    @Query(value = "select * from article a where a.id = :id for update", nativeQuery = true)
    Optional<Article> findArticleForUpdate(Long id);
}

利用JPA的@Lock行鎖注解解決并發(fā)問題

如果說for update的做法太原始,那么JPA有提供一個更加優(yōu)雅的方法,就是@Lock注解 .

為Repository添加JPA的鎖方法,其中LockModeType.PESSIMISTIC_WRITE參數(shù)就是行鎖。

關(guān)于LockModeType這個類型,可以在這找到文檔 https://docs.oracle.com/javaee/7/api/javax/persistence/LockModeType.html

  • NONE: No lock.
  • OPTIMISTIC: Optimistic lock.
  • OPTIMISTIC_FORCE_INCREMENT: Optimistic lock, with version update.
  • PESSIMISTIC_FORCE_INCREMENT: Pessimistic write lock, with version update.
  • PESSIMISTIC_READ: Pessimistic read lock.
  • PESSIMISTIC_WRITE: Pessimistic write lock.
  • READ: Synonymous with OPTIMISTIC.
  • WRITE: Synonymous with OPTIMISTIC_FORCE_INCREMENT.
public interface ArticleRepository extends JpaRepository<Article, Long> { 
    @Lock(value = LockModeType.PESSIMISTIC_WRITE)
    @Query("select a from Article a where a.id = :id")
    Optional<Article> findArticleWithPessimisticLock(Long id);
}

如果是@NameQuery,則可以

@NamedQuery(name="lockArticle",query="select a from Article a where a.id = :id",lockMode = PESSIMISTIC_READ)
public class Article

如果用entityManager的方式,則可以設(shè)置LocakMode:

 Query query = entityManager.createQuery("from Article where articleId = :id");
 query.setParameter("id", id);
 query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
 query.getResultList();

樂觀鎖與并發(fā)

樂觀鎖(Optimistic Lock),顧名思義,就是很樂觀,每次去拿數(shù)據(jù)的時候都認(rèn)為別人不會修改,所以不會上鎖,但是在提交更新的時候會判斷一下在此期間別人有沒有去修改。所以悲觀鎖是限制其他線程,而樂觀鎖是限制自己,雖然他的名字有鎖,但是實際上不算上鎖,通常為version版本號機制,還有CAS算法 .

利用version字段解決并發(fā)問題

版本號機制就是在數(shù)據(jù)庫中加一個字段version當(dāng)作版本號。那么獲取Article的時候就會帶一個版本號,比如version=1,然后你對這個Article一波操作,操作完之后要插入到數(shù)據(jù)庫了。

校驗一下version版本號,發(fā)現(xiàn)在數(shù)據(jù)庫里對應(yīng)Article記錄的version=2,這和我手里的版本不一樣啊,說明提交的Article不是最新的,那么就不能update到數(shù)據(jù)庫了,進行報錯把,這樣就避免了并發(fā)時數(shù)據(jù)沖突的問題。

public interface ArticleRepository extends JpaRepository<Article, Long> {
    @Modifying
    @Query(value = "update article set content= :content, version = version + 1 where id = :id and version = :version", nativeQuery = true)
    int updateArticleWithVersion(Long id, String content, Long version);
}
public void postComment(Long articleId, String content) {
 //get article
    Optional<Article> articleOptional = articleRepository.findById(articleId);
    //update with Optimistic Lock
    int count = articleRepository.updateArticleWithVersion(article.getId(), content, article.getVersion());
  
    if (count == 0) {
        throw new RuntimeException("更新數(shù)據(jù)失敗,請刷新重試");
    }else{
     articleRepository.save(article);
    } 
}

利用JPA的@Version版本機制解決并發(fā)問題

有沒有更優(yōu)雅的方式? 當(dāng)然,必須有,那就是JPA自帶的@Version方式實現(xiàn)樂觀鎖。

  • each entity class must have only one version attribute .每個實體類只能有一個@Version字段,不能多
  • it must be placed in the primary table for an entity mapped to several tables . 對于映射到多個表的實體,必須將其放置在主表中
  • type of a version attribute must be one of the following: int, Integer, long, Long, short, Short, java.sql.Timestamp ,

@Version支持的類型必須是以下類型:

  • int
  • Integer
  • long
  • Long
  • short
  • Short
  • java.sql.Timestamp

首先在Article實體類的version字段上加上@Version注解

@Data
@Entity
public class Article{ 
    @Id
    private Long id;  
  //......  
    @Version
    private Integer version; 
}
Article article = entityManager.find(Article.class, id);
entityManager.lock(article , LockModeType.OPTIMISTIC);
entityManager.refresh(article , LockModeType.READ);

什么時候用悲觀鎖或者樂觀鎖

悲觀鎖適合寫多讀少的場景。因為在使用的時候該線程會獨占這個資源,就適合用悲觀鎖,否則用戶只是瀏覽文章的話,用悲觀鎖就會經(jīng)常加鎖,增加了加鎖解鎖的資源消耗。

樂觀鎖適合寫少讀多的場景。由于樂觀鎖在發(fā)生沖突的時候會回滾或者重試,如果寫的請求量很大的話,就經(jīng)常發(fā)生沖突,結(jié)合事務(wù)會有經(jīng)常的回滾和重試,這樣對系統(tǒng)資源消耗也是非常大。

所以悲觀鎖和樂觀鎖沒有絕對的好壞,必須結(jié)合具體的業(yè)務(wù)情況來決定使用哪一種方式。另外在阿里巴巴開發(fā)手冊里也有提到:

如果每次訪問沖突概率小于 20%,推薦使用樂觀鎖,否則使用悲觀鎖。樂觀鎖的重試次數(shù)不得小于3次。

阿里巴巴建議以沖突概率20%這個數(shù)值作為分界線來決定使用樂觀鎖和悲觀鎖,雖然說這個數(shù)值不是絕對的,但是作為阿里巴巴各個大佬總結(jié)出來的也是一個很好的參考。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot 配置提示功能(超詳細)

    SpringBoot 配置提示功能(超詳細)

    這篇文章主要介紹了SpringBoot 配置提示功能,本文給大家介紹的超詳細,通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-10-10
  • Java字符串相關(guān)類操作方法詳解

    Java字符串相關(guān)類操作方法詳解

    這篇文章主要給大家介紹了關(guān)于Java字符串相關(guān)類操作的相關(guān)資料,文中還特別介紹了字符串的定義、構(gòu)造方法、內(nèi)存原理、比較方法和常見方法,同時還介紹了StringBuilder和StringJoiner類,需要的朋友可以參考下
    2024-12-12
  • Java發(fā)送http請求的示例(get與post方法請求)

    Java發(fā)送http請求的示例(get與post方法請求)

    這篇文章主要介紹了Java發(fā)送http請求的示例(get與post方法請求),幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2021-01-01
  • 如何用Intellij idea2020打包jar的方法步驟

    如何用Intellij idea2020打包jar的方法步驟

    這篇文章主要介紹了如何用Intellij idea 2020打包jar的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • java  多線程的三種構(gòu)建方法

    java 多線程的三種構(gòu)建方法

    這篇文章主要介紹了java 多線程的三種構(gòu)建方法的相關(guān)資料,這里提供三種實現(xiàn)方法,希望大家能夠掌握,很重要的基礎(chǔ)知識,需要的朋友可以參考下
    2017-09-09
  • 打開.properties中文顯示unicode編碼問題以及解決

    打開.properties中文顯示unicode編碼問題以及解決

    這篇文章主要介紹了打開.properties中文顯示unicode編碼問題以及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • java日期相關(guān)類實例詳解

    java日期相關(guān)類實例詳解

    這篇文章主要介紹了java日期相關(guān)類實例詳解,小編覺得還是挺不錯的,這里分享給大家,供需要的朋友參考。
    2017-10-10
  • SpringBoot整合Elasticsearch游標(biāo)查詢的示例代碼(scroll)

    SpringBoot整合Elasticsearch游標(biāo)查詢的示例代碼(scroll)

    這篇文章主要介紹了SpringBoot整合Elasticsearch游標(biāo)查詢(scroll),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • Java RPC框架過濾器機制原理解析

    Java RPC框架過濾器機制原理解析

    這篇文章主要介紹了Java RPC框架過濾器機制原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • java使用DOM對XML文檔進行增刪改查操作實例代碼

    java使用DOM對XML文檔進行增刪改查操作實例代碼

    這篇文章主要介紹了java使用DOM對XML文檔進行增刪改查操作實例代碼,實例涉及對xml文檔的增刪改查,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02

最新評論

东宁县| 连平县| 田阳县| 芜湖市| 定南县| 郁南县| 泌阳县| 方城县| 嵊州市| 来凤县| 天长市| 大宁县| 印江| 荃湾区| 博客| 太仆寺旗| 新昌县| 遵化市| 隆昌县| 诏安县| 信丰县| 木里| 西平县| 徐水县| 恩平市| 迁西县| 罗田县| 邢台市| 桑植县| 伊通| 新余市| 北川| 光泽县| 阿瓦提县| 米易县| 应用必备| 栾川县| 定结县| 浠水县| 东安县| 巴中市|