日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Java 并發編程的可見性、有序性和原子性

瀏覽:33日期:2022-08-21 09:00:59

并發編程無論在哪門語言里,都屬于高級篇,面試中也嘗嘗會被問到。想要深入理解并發編程機制確實不是一件容易的事,因為它涉及到計算機底層和操作系統的相關知識,如果對這部分知識不是很清楚可能會導致理解困難。

在這個專欄里,王子會盡量以白話和圖片的方式剖析并發編程本質,希望可以讓大家更容易理解。

今天我們就來談一談可見性、有序性和原子性都是什么東西。

并發編程的幕后

進入主題之前,我們先來了解一下并發編程的幕后。

隨著CPU、內存和I/O設備的不斷升級,它們之間一直存在著一個矛盾,就是速度不一致問題。CPU的速度高于內存,內存的速度又高于I/O設備。

我們寫的代碼中大多數內容都會經過內存處理,有些內容會去讀寫I/O設備,根據木桶理論,整體的性能取決于最慢的操作,就是I/O設備,所以單單提升CPU的性能是不夠的。

為了最大化體現出CPU的性能,計算機底層主要做了三部分優化:

1.CPU增加了緩存,比內存速度更快,平衡內存的速度

2.操作系統增加了進程和線程,可以對CPU分時復用

3.編譯程序會進行指令的重排,使緩存更好的發揮性能

我們平時的工作中其實一直都享受著這些優化后的成果,但同時他們也會導致一些很難找到原因的BUG。

什么是可見性

首先我們就來看看什么是可見性。

一個線程對共享變量的修改,另一個線程可以感知到,我們稱其為可見性。

在單核時代,其實是不存在可見性問題的,因為所有的線程都是在一個CPU中工作的,一個線程的寫操作對于其他的線程一定是可見的。

Java 并發編程的可見性、有序性和原子性

但是多核CPU出現后,每個CPU都有自己的緩存,多個線程在不同的CPU中處理數據就會導致不可見問題。

Java 并發編程的可見性、有序性和原子性

假設變量v的值是1, 兩個線程同時執行了v++操作,首先會從內存中讀取變量v的數據到各自的CPU緩存中,這個時候兩個CPU緩存中的v都是1,執行v++后,兩個變量v都變成了2,然后再寫回內存,內存中的變量v就變成了2。

但其實我們想看到的結果v最終應該是3才對。

在CPU1緩存中執行v++后,CPU2緩存無法感知的到,這就是可見性問題。而由于可見性問題導致的最終數據不正確,就是線程安全問題。

什么是原子性

由于I/O的速度太慢,早期的操作系統發明了多進程,就是允許某個進程執行一小段時間后,重新選擇一個進程來執行,這個過程叫做任務切換,而這一小段的時間我們稱其為時間片。

Java 并發編程的可見性、有序性和原子性

現在操作系統的任務切換一般指的是更輕量級的線程切換,java的并發編程是基于多線程的,自然也會存在線程切換。

一般會在時間片結束的時候進行線程切換,java語言中執行的一段簡單的代碼往往需要多條CPU的指令實現,比如count++這部分代碼,至少需要三條CPU指令:

1.首先把count從內存中讀取到CPU的寄存器中

2.在寄存器中執行+1操作

3.最后將count的值寫入內存中(可能寫入到CPU的緩存中)

而線程切換是可以發生在任意的一條CPU指令執行之后的,注意,這里說的是CPU的指令,而不是java語言中的指令,對于上面的三條指令來說,我們假設 count=0,如果線程 A 在指令 1 執行完后做線程切換,線程 A 和線程 B 按照下圖的順序執行,那么我們會發現兩個線程都執行了 count++ 的操作,但是得到的結果不是我們期望的 2,而是 1。

Java 并發編程的可見性、有序性和原子性

這就是線程切換導致的數據錯誤問題,我們把一個或者多個操作在 CPU 執行的過程中不被中斷的特性稱為原子性,CPU 能保證的原子操作是 CPU 指令級別的,而不是高級語言的操作符,這是違背我們直覺的地方。因此,很多時候我們需要在高級語言層面保證操作的原子性。

什么是有序性

有序性指的是程序按照代碼的先后順序執行。編譯器為了優化性能,有時候會改變程序中語句的先后順序,例如程序中:“x=1;y=2;”編譯器優化后可能變成“y=2;x=1;”。

在這個例子中,編譯器調整了語句的順序,但是不影響程序的最終結果。不過有時候調整了語句的順序可能導致意想不到的 Bug。

在 Java 領域一個經典的案例就是利用雙重檢查創建單例對象,代碼如下:

public class Singleton { static Singleton instance; static Singleton getInstance(){ if (instance == null) { synchronized(Singleton.class) { if (instance == null) instance = new Singleton(); } } return instance; }}

假設有兩個線程 A、B 同時調用 getInstance() 方法,他們會同時發現 instance == null ,于是同時對 Singleton.class 加鎖,此時 JVM 保證只有一個線程能夠加鎖成功(假設是線程 A),另外一個線程則會處于等待狀態(假設是線程 B);線程 A 會創建一個 Singleton 實例,之后釋放鎖,鎖釋放后,線程 B 被喚醒,線程 B 再次嘗試加鎖,此時是可以加鎖成功的,加鎖成功后,線程 B 檢查 instance == null 時會發現,已經創建過 Singleton 實例了,所以線程 B 不會再創建一個 Singleton 實例。

這個過程看上去是不是無懈可擊,沒有漏洞?

答案是否定的,問題就出在了new操作上,我們以為的new操作是這樣的:

1.分配一塊內存空間

2.在這塊內存空間上初始化Singleton實例對象

3.把這個對象的內存地址賦值給instance變量

但實際上由于指令重排,優化后的過程是這樣的:

1.分配一塊內存空間

2.把這快內存空間的內存地址賦值給instance變量

3.在這塊內存空間上初始化Singleton實例對象

那么這樣調換順序后會發生什么呢?

我們假設線程 A 先執行 getInstance() 方法,當執行完指令 2 時恰好發生了線程切換,切換到了線程 B 上;如果此時線程 B 也執行 getInstance() 方法,那么線程 B 在執行第一個判斷時會發現 instance != null ,所以直接返回 instance,而此時的 instance 是沒有初始化過的,如果我們這個時候訪問 instance 的成員變量就可能觸發空指針異常。

總結

使用并發編程開發,往往會出現很多難以找到原因的BUG,通過對可見性、有序性和原子性的分析,可以為我們排查并發導致的BUG提供一些思路。

CPU緩存會導致可見性

指令重排會導致有序性

線程切換會導致原子性

以上就是本篇文章的三個核心內容,那我們下篇文章繼續。

以上就是Java 并發編程的可見性、有序性和原子性的詳細內容,更多關于Java 并發編程的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品日韩精品在线播放| 欧美私人啪啪vps| 国产精品传媒麻豆hd| 日韩av中文字幕一区二区| 日本欧美韩国一区三区| 国产欧美久久一区二区三区| 成人国产精品一区二区免费麻豆| 成人日韩精品| 欧美 日韩 国产精品免费观看| 激情久久中文字幕| 亚洲一区二区免费在线观看| 欧美在线看片| 日韩专区精品| 伊人精品一区| 午夜精品影视国产一区在线麻豆| 国产精品男女| 日韩精品免费一区二区在线观看| 免费久久精品| 日韩精品国产精品| 国产精品久久久久久久久久10秀| 香蕉国产精品| 97久久超碰| 亚洲天堂1区| 亚洲一二av| 国产一区二区三区视频在线| 午夜精品影院| 欧美国产视频| 五月综合激情| 日本在线视频一区二区| 精品视频久久| 午夜国产精品视频免费体验区| 日韩中文字幕一区二区高清99| 免费一级欧美片在线观看网站| 99精品在线免费在线观看| 一区二区精品| 在线亚洲人成| 奇米亚洲欧美| 亚洲欧美伊人| 国产精品久久久久久久久久妞妞| 日韩欧美一区二区三区免费观看| 一区二区精彩视频| 日韩激情一区| 日韩av资源网| 欧美三级网址| 欧美天堂在线| 美女久久网站| 久久国产主播| 免费在线亚洲| 视频一区视频二区中文字幕| 丰满少妇一区| 91精品国产自产精品男人的天堂| 久久久蜜桃一区二区人| 国产精品久久久久9999高清| 欧美日韩视频| 久久男人av资源站| 国产精品一区亚洲| 国产视频一区在线观看一区免费| 欧美xxxx中国| 五月激激激综合网色播| 日韩中文在线播放| 国产精品3区| 日韩极品在线观看| 夜夜嗨一区二区三区| 精精国产xxxx视频在线播放| 欧美激情一区| 亚洲日本久久| 日韩视频在线一区二区三区 | 国产精品日本一区二区不卡视频| 91国语精品自产拍| 国产精品久久久久久久久妇女| 日韩黄色av| 蜜臀久久久久久久| 好看不卡的中文字幕| 视频二区不卡| 国内在线观看一区二区三区 | 日本不卡一二三区黄网| 免费视频一区三区| 欧美精品日日操| 久久影院午夜精品| 正在播放日韩精品| 麻豆久久久久久久| 国产精品永久| 国产欧美一区二区三区国产幕精品| 亚洲午夜免费| 中文字幕日韩亚洲| 亚洲网址在线观看| 日韩专区在线视频| 午夜在线一区| 久久xxxx| 亚洲视频电影在线| 亚州国产精品| 亚洲狼人精品一区二区三区| 欧美中文字幕| 中文字幕av一区二区三区人| 蜜桃91丨九色丨蝌蚪91桃色| 亚洲精品一区二区在线看| 亚洲一级黄色| 伊人久久成人| 久久99伊人| 在线观看一区| 91av一区| 国产一区二区三区久久 | 日韩精品视频网站| 久久国产视频网| 久久不见久久见免费视频7| 久久久久九九精品影院| 高清久久精品| 免费高潮视频95在线观看网站| 免费观看亚洲| 亚洲精品国产嫩草在线观看| 亚洲不卡av不卡一区二区| 99久久夜色精品国产亚洲狼| 欧美jjzz| 中文字幕乱码亚洲无线精品一区| 日韩高清在线不卡| 久久99蜜桃| 亚洲一区资源| 亚洲少妇在线| 日韩精品一区二区三区中文| 欧美激情视频一区二区三区免费| 在线天堂中文资源最新版| 日韩一级不卡| 97精品久久| 精品三级国产| 一区二区三区视频免费观看| 中文字幕一区二区三区四区久久| 久久精品 人人爱| 欧美久久天堂| 免费视频最近日韩| 美腿丝袜亚洲一区| 欧美综合另类| 欧美在线观看天堂一区二区三区| 国产aⅴ精品一区二区三区久久| 国产一区日韩欧美| 欧美一区不卡| 极品裸体白嫩激情啪啪国产精品| 日韩欧美2区| 精品国产一区二区三区av片| 在线日韩av| 国产精品久久亚洲不卡| 激情综合自拍| 国产精品第一国产精品| 99久久九九| 久久国产精品色av免费看| 久久久久99| 国产精品videossex久久发布| 欧美成人综合| 精品亚洲a∨一区二区三区18| 亚洲欧美日韩综合国产aⅴ| 久久精品伊人| 亚洲va久久久噜噜噜久久| 日本午夜大片a在线观看| 男女激情视频一区| 丁香婷婷久久| 日韩动漫一区| 亚洲国产专区校园欧美| 黄色成人精品网站| 福利精品在线| 欧美日本三区| 免费在线观看视频一区| 91精品韩国| 国产精品久久久久av蜜臀| 尤物在线精品| 超碰在线99| 欧美视频一区| 久久亚洲不卡| 久久中文字幕av| 国产精品a级| 亚洲精品观看| av不卡在线| 久久国产亚洲| 麻豆mv在线观看| 久久爱www.| 91福利精品在线观看| 视频一区视频二区中文字幕| 99精品电影| 中文字幕成在线观看| 国产精品一区高清| 日韩欧美中文字幕一区二区三区| 国产一区白浆| 欧美成人亚洲| 亚洲91视频| 日韩一区二区三区免费播放| 日本a口亚洲| 午夜久久av| 美女黄网久久| 黄色日韩在线| 亚洲精品2区| 亚洲女同中文字幕| 国产字幕视频一区二区| 偷拍精品精品一区二区三区| 福利欧美精品在线| 国产一区二区三区黄网站| 欧美激情麻豆| 国产精品一线| 国产精品sss在线观看av| 欧美日韩网址| 国产精品久久久久久模特| 综合激情五月婷婷| 婷婷久久免费视频|