国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

雙重檢查鎖,原來是這樣演變來的,你了解嗎

開發(fā) 前端
在看Nacos的源代碼時,發(fā)現(xiàn)多處都使用了“雙重檢查鎖”的機制,算是非常好的實踐案例。這篇文章就著案例來分析一下雙重檢查鎖的使用以及優(yōu)勢所在,目的就是讓你的代碼格調更加高一個層次。

[[417932]]

本文轉載自微信公眾號「程序新視界」,作者二師兄。轉載本文請聯(lián)系程序新視界公眾號。

在看Nacos的源代碼時,發(fā)現(xiàn)多處都使用了“雙重檢查鎖”的機制,算是非常好的實踐案例。這篇文章就著案例來分析一下雙重檢查鎖的使用以及優(yōu)勢所在,目的就是讓你的代碼格調更加高一個層次。

同時,基于單例模式,講解一下雙重檢查鎖的演變過程。

Nacos中的雙重檢查鎖

在Nacos的InstancesChangeNotifier類中,有這樣一個方法:

  1. private final Map<String, ConcurrentHashSet<EventListener>> listenerMap = new ConcurrentHashMap<String, ConcurrentHashSet<EventListener>>(); 
  2.  
  3. private final Object lock = new Object(); 
  4.  
  5. public void registerListener(String groupName, String serviceName, String clusters, EventListener listener) { 
  6.     String key = ServiceInfo.getKey(NamingUtils.getGroupedName(serviceName, groupName), clusters); 
  7.     ConcurrentHashSet<EventListener> eventListeners = listenerMap.get(key); 
  8.     if (eventListeners == null) { 
  9.         synchronized (lock) { 
  10.             eventListeners = listenerMap.get(key); 
  11.             if (eventListeners == null) { 
  12.                 eventListeners = new ConcurrentHashSet<EventListener>(); 
  13.                 listenerMap.put(key, eventListeners); 
  14.             } 
  15.         } 
  16.     } 
  17.     eventListeners.add(listener); 

該方法的主要功能就是對監(jiān)聽器事件進行注冊。其中注冊的事件都存在成員變量listenerMap當中。listenerMap的數(shù)據結構是key為String,value為ConcurrentHashSet的Map。也就是說,一個key對應一個集合。

針對這種數(shù)據結構,在多線程的情況下,Nacos處理流程如下:

  • 通過key獲取value值;
  • 判斷value是否為null;
  • 如果value值不為null,則直接將值添加到Set當中;
  • 如果為null,就需要創(chuàng)建一個ConcurrentHashSet,在多線程時,有可能會創(chuàng)建多個,因此要使用鎖。
  • 通過synchronized鎖定一個Object對象;
  • 在鎖內再獲取一次value值,如果依然是null,則進行創(chuàng)建。
  • 進行后續(xù)操作。

上述過程,在鎖定前和鎖定之后,做了兩次判斷,因此稱作”雙重檢查鎖“。使用鎖的目的就是避免創(chuàng)建多個ConcurrentHashSet。

Nacos中的實例稍微復雜一下,下面以單例模式中的雙重檢查鎖的演變過程。

未加鎖的單例

這里直接演示單例模式的懶漢模式實現(xiàn):

  1. public class Singleton { 
  2.      
  3.     private static Singleton instance; 
  4.      
  5.     private Singleton() { 
  6.     } 
  7.      
  8.     public Singleton getInstance() { 
  9.         if (instance == null) { 
  10.             instance = new Singleton(); 
  11.         } 
  12.         return instance; 
  13.     }     

這是一個最簡單的單例模式,在單線程下運轉良好。但在多線程下會出現(xiàn)明顯的問題,可能會創(chuàng)建多個實例。

以兩個線程為例:

可以看到,當兩個線程同時執(zhí)行時,是有可能會創(chuàng)建多個實例的,這很明顯不符合單例的要求。

加鎖單例

針對上述代碼的問題,很直觀的想到是進行加鎖處理,實現(xiàn)代碼如下:

  1. public class Singleton { 
  2.      
  3.     private static Singleton instance; 
  4.      
  5.     private Singleton() { 
  6.     } 
  7.      
  8.     public synchronized Singleton getInstance() { 
  9.         if (instance == null) { 
  10.             instance = new Singleton(); 
  11.         } 
  12.         return instance; 
  13.     } 

與第一個示例唯一的區(qū)別是在方法上添加了synchronized關鍵字。這時,當多個線程進入該方法時,需要先獲得鎖才能進行執(zhí)行。

通過在方法上添加synchronized關鍵字,看似完美的解決了多線程的問題,但卻帶了性能問題。

我們知道使用鎖會導致額外的性能開銷,對于上面的單例模式,只有第一次創(chuàng)建時需要鎖(防止創(chuàng)建多個實例),但查詢時是不需要鎖的。

如果針對方法進行加鎖,每次查詢也要承擔加鎖的性能損耗。

雙重檢查鎖

針對上面的問題,就有了雙重檢查鎖,示例如下:

  1. public class Singleton { 
  2.      
  3.     private static Singleton instance; 
  4.      
  5.     private Singleton() { 
  6.     } 
  7.      
  8.     public Singleton getInstance() { 
  9.         if (instance == null) { 
  10.             synchronized (Singleton.class) { 
  11.                 if (instance == null) { 
  12.                     instance = new Singleton(); 
  13.                 } 
  14.             } 
  15.         } 
  16.         return instance; 
  17.     } 

第一,將鎖的范圍縮小的方法內;

第二,鎖之前先判斷一下是不是null,如果不為null,說明已經實例化了,直接返回,沒必要進行創(chuàng)建;

第三,如果為null,進行加鎖,然后再次判斷是否為null。為什么要再次判斷?因為一個線程判斷為null之后,另外一個線程可能已經創(chuàng)建了對象,所以在鎖定之后,需要再次核實一下,真的為null,則進行對象創(chuàng)建。

改進之后,既保證了線程的安全性,又避免了鎖導致的性能損失。問題到此結束了嗎?并沒有,繼續(xù)往下看。

JVM的指令重排

在某些JVM當中,編譯器為了性能問題,會進行指令重排。在上述代碼中new Singleton()并不是原子操作,有可能會被編譯器進行重排操作。

創(chuàng)建對象可抽象為三步:

  1. memory = allocate();    //1:分配對象的內存空間  
  2. ctorInstance(memory);  //2:初始化對象  
  3. instance = memory;     //3:設置instance指向剛分配的內存地址 

上面操作中,操作2依賴于操作1,但操作3并不依賴于操作2。因此,JVM是可以進行指令重排優(yōu)化的,可能會出現(xiàn)如下的執(zhí)行順序:

  1. memory = allocate();    //1:分配對象的內存空間  
  2. instance = memory;     //3:instance指向剛分配的內存地址,此時對象還未初始化 
  3. ctorInstance(memory);  //2:初始化對象 

指令重排之后,將操作3的賦值操作放在了前面,那就會出現(xiàn)一個問題:當線程A執(zhí)行完步驟賦值操作,但還未執(zhí)行對象初始化。此時,線程B進來了,在第一層判斷時發(fā)現(xiàn)Instance已經有值了(實際上還未初始化),直接返回對應的值。那么,程序在使用這個未初始化的值時,便會出現(xiàn)錯誤。

針對此問題,可在instance上添加volatile關鍵字,使得instance在讀、寫操作前后都會插入內存屏障,避免重排序。

最終,單例模式實現(xiàn)如下:

  1. public class Singleton { 
  2.      
  3.     private static volatile Singleton instance; 
  4.      
  5.     private Singleton() { 
  6.     } 
  7.      
  8.     public Singleton getInstance() { 
  9.         if (instance == null) { 
  10.             synchronized (Singleton.class) { 
  11.                 if (instance == null) { 
  12.                     instance = new Singleton(); 
  13.                 } 
  14.             } 
  15.         } 
  16.         return instance; 
  17.     } 

至此,一個完善的單例模式實現(xiàn)了。此時,你是否有一個疑問,為什么Nacos中的雙重檢查鎖沒有使用volatile關鍵字呢?

答案很簡單:上面單例模式如果出現(xiàn)指令重排,會導致單例實例被使用。那么,再看Nacos的代碼,由于創(chuàng)建ConcurrentHashSet并不會影響到查詢,而真正影響查詢的是listenerMap.put方法,而ConcurrentHashSet本身是線程安全的。因此,也就不會出現(xiàn)線程安全問題,不用使用volatile關鍵字了。

小結

閱讀源碼最有意思的一個地方就是可以看到很多經典知識的實踐,如果能夠深入思考,拓展一下,會獲得意想不到的收獲。

再回顧一下本文的重點:

  • 閱讀Nacos源碼,發(fā)現(xiàn)雙重檢查鎖的使用;
  • 未加鎖單例模式使用,會創(chuàng)建多個對象;
  • 方法上加鎖,導致性能下降;
  • 代碼內局部加鎖,雙重判斷,既滿足線程安全,又滿足性能需求;
  • 單例模式特例:創(chuàng)建對象分多步,會出現(xiàn)指令重排現(xiàn)象,采用volatile進行避免指令重排。

 

責任編輯:武曉燕 來源: 程序新視界
相關推薦

2022-12-14 07:32:40

InnoDBMySQL引擎

2018-04-02 15:13:21

網絡

2023-02-15 08:17:38

2024-04-30 08:22:51

Figma圖形編輯變換矩陣

2025-02-17 09:22:16

MySQLSQL語句

2014-07-21 10:32:52

蘋果公司實習

2022-05-05 08:55:12

工業(yè)物聯(lián)網IIoT

2023-05-22 15:58:11

2024-02-06 09:30:25

Figma矩形矩形物理屬性

2020-05-26 08:52:36

Java JVM多態(tài)

2022-05-09 08:37:43

IO模型Java

2020-11-24 06:20:02

Linux日志文件系統(tǒng)

2016-10-12 08:54:24

2025-11-24 09:01:03

Flink內存模型

2009-03-11 14:42:57

面試求職案例

2015-03-25 09:55:34

程序員程序員修補BUG真正原因

2018-10-26 10:41:19

2020-03-23 08:30:12

程序員男友感受

2022-07-13 10:37:59

服務器故障優(yōu)化

2017-05-09 15:39:33

ensorFlow機器人機器學習
點贊
收藏

51CTO技術棧公眾號

欧美在线一区二区视频| 亚洲最大中文字幕| 国内精品视频免费| 精品午夜视频| 欧美日韩免费看| 欧美日韩在线精品| 欧美aaaaaaaa牛牛影院| 夜夜夜精品看看| 91视频 -- 69xx| 一本久久知道综合久久| 久久九九免费视频| 国产伦久视频在线观看| 亚洲自拍偷拍图区| 亚洲色欲综合一区二区三区| 日韩国产成人精品| 欧美精品七区| 午夜久久黄色| 91精品国产99久久久久久红楼| 91麻豆精品| 欧美日韩第一区日日骚| 国产小视频精品| 国产精品1区2区3区| 亚洲欧美综合一区| 久久99精品久久只有精品| 国产精品三级网站| 日韩欧美一区二区三区免费看| 日韩色在线观看| 亚洲自拍中文字幕| 阿v视频在线| 妖精一区二区三区精品视频 | 日韩欧美高清在线视频| 亚洲一区不卡在线| 中文字幕一区二区三三| 国产伦精品一区二区三区免| 91啦中文在线观看| 亚州欧美日韩中文视频| 美女午夜精品| 欧美在线www| 日韩欧美高清| 国产美女高潮久久白浆| 在线成人h网| 国外成人性视频| 精品大片一区二区| 亚洲自拍中文字幕| 最新日韩在线| 久久天天东北熟女毛茸茸| av不卡在线播放| 精品一区二区三区国产| 视频一区在线视频| 日本中文字幕在线视频观看| 国产精品私人影院| 久久av综合网| 国产精品亚洲欧美日韩一区在线| 国产精品私人影院| 国产小视频免费在线网址| 亚洲美女av在线播放| 色老板在线视频一区二区| 欧美午夜免费| 精品一区二区在线视频| 日本高清不卡中文字幕| 亚洲精品久久久久中文字幕欢迎你| 美女视频亚洲色图| 2018中文字幕第一页| 成人免费小视频| 日韩有码欧美| 亚洲高清在线播放| 色诱视频网站一区| 亚洲va欧美va人人爽成人影院| 欧美国产日韩视频| 麻豆成人在线观看| 成年网站在线| 国产精品极品在线| 国产精品色哟哟| 外国成人直播| 性欧美精品一区二区三区在线播放 | 精品免费99久久| 亚洲欧美文学| 青青免费在线视频| 美女久久久久久久| a亚洲天堂av| 欧美bbbxxxxx| 亚洲精品在线免费| 91精品欧美福利在线观看| 国产精品第十页| 成人在线免费公开观看视频| 2022国产精品| 欧美视频你懂的| 亚洲精选在线| 狠狠躁少妇一区二区三区| 亚洲国产sm捆绑调教视频| 国产成人一二片| av网站观看| 国产精品亚洲美女av网站| 国产亚洲短视频| 欧美日中文字幕| 欧美vide| 国产一区二区视频在线免费观看| 欧美色图片你懂的| 日韩成人一级大片| 18加网站在线| 日本中文字幕在线视频观看 | av资源在线观看免费高清| 欧美另类一区| 国产丝袜一区视频在线观看| 91视频.com| 国产一区二区三区探花| 国产香蕉视频在线看| 欧美精品一区二区三区在线四季 | 久久免费成人精品视频| 亚洲一区二区三区美女| 一本不卡影院| 色婷婷综合久久久久| 成人av网址在线观看| 久久99久久人婷婷精品综合| 成年人网站在线| 丰满少妇在线观看| 日韩精品一区二区三区四区五区 | 欧美高清在线观看| 欧美喷潮久久久xxxxx| 日本一二三不卡| 欧美日本一区| 天堂久久午夜av| 午夜视频在线| 日韩国产一级片| a级国产乱理论片在线观看99| 国产亚洲精品福利| 欧美午夜一区二区福利视频| 91麻豆精品国产综合久久久 | 久久久亚洲网站| 欧美日韩黄色影视| 国产精品夫妻自拍| 国产69精品久久久久毛片| 99久久.com| 九九精品调教| 成人日韩欧美| 视频二区在线| 一个人看的免费视频色| www.色就是色| 麻豆md0077饥渴少妇| 国产精品av一区| 免费成人在线观看| 国产午夜电影| 青草青青在线视频| 亚洲国产午夜伦理片大全在线观看网站| 欧美亚洲在线观看| 欧美最猛性xxxxx免费| 精品国产一区二区三区不卡| 91精品国产综合久久精品app| 亚洲精品一卡二卡| 成人自拍视频在线观看| www.66久久| 久久国产电影| 国产精品成人**免费视频| 在线免费av资源| 成人精品国产| 黄色一级片视频| 五月婷婷激情综合| 91丨porny丨国产入口| 91原创在线视频| 久久久久久日产精品| 一区二区在线观看免费| 国产精品香蕉一区二区三区| 99视频在线观看一区三区| 高清视频一区二区| 亚洲综合丝袜美腿| 中文字幕一区二区不卡| 国产欧美一区二区在线| 久久久99久久| 91麻豆.com| 欧美日韩国产在线看| 欧美一级在线视频| 欧美极度另类性三渗透| 欧美日韩国产成人| 8050国产精品久久久久久| 久久婷婷开心| 好吊妞www.84com只有这里才有精品 | 欧美一性一交| 欧美91福利在线观看| 麻豆高清免费国产一区| 免费看日韩精品| 久久婷婷久久一区二区三区| 中文字幕一区二区三| 日韩精品一区二区三区在线观看| 欧美高清视频在线观看| 精品日本一区二区三区| 四虎影视永久免费观看| 老牛影视精品| 国模私拍一区二区国模曼安| 日韩影视高清在线观看| 久久精品国产99| 欧美日韩中文另类| 欧美黄色成人网| 亚洲精品第一区二区三区| 9l视频白拍9色9l视频| 色戒汤唯在线观看| 日韩视频一区二区三区四区| 久久精品国产秦先生| 欧美午夜激情小视频| 国产婷婷色综合av蜜臀av| 午夜老司机精品|