电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

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

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

瀏覽:19日期: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
相關文章:
主站蜘蛛池模板: 耐磨陶瓷,耐磨陶瓷管道_厂家-淄博拓创陶瓷科技 | 工业车间焊接-整体|集中除尘设备-激光|等离子切割机配套除尘-粉尘烟尘净化治理厂家-山东美蓝环保科技有限公司 | 儿童乐园|游乐场|淘气堡招商加盟|室内儿童游乐园配套设备|生产厂家|开心哈乐儿童乐园 | 风信子发稿-专注为企业提供全球新闻稿发布服务 | 风淋室生产厂家报价_传递窗|送风口|臭氧机|FFU-山东盛之源净化设备 | 生态板-实木生态板-生态板厂家-源木原作生态板品牌-深圳市方舟木业有限公司 | 多功能干燥机,过滤洗涤干燥三合一设备-无锡市张华医药设备有限公司 | 石膏基自流平砂浆厂家-高强石膏基保温隔声自流平-轻质抹灰石膏粉砂浆批发-永康市汇利建设有限公司 | 山东led显示屏,山东led全彩显示屏,山东LED小间距屏,临沂全彩电子屏-山东亚泰视讯传媒有限公司 | 多功能真空滤油机_润滑油全自动滤油机_高效真空滤油机价格-重庆润华通驰 | 蚂蚁分类信息系统 - PHP同城分类信息系统 - MayiCMS | 微型气象仪_气象传感器_防爆气象传感器-天合传感器大全 | 刺绳_刀片刺网_刺丝滚笼_不锈钢刺绳生产厂家_安平县浩荣金属丝网制品有限公司-安平县浩荣金属丝网制品有限公司 | 铝箔袋,铝箔袋厂家,东莞铝箔袋,防静电铝箔袋,防静电屏蔽袋,防静电真空袋,真空袋-东莞铭晋让您的产品与众不同 | 青岛成人高考_山东成考报名网| 铝扣板-铝方通-铝格栅-铝条扣板-铝单板幕墙-佳得利吊顶天花厂家 elisa试剂盒价格-酶联免疫试剂盒-猪elisa试剂盒-上海恒远生物科技有限公司 | 联系我们老街华纳娱乐公司官网19989979996(客服) | 护腰带生产厂家_磁石_医用_热压护腰_登山护膝_背姿矫正带_保健护具_医疗护具-衡水港盛 | 理化生实验室设备,吊装实验室设备,顶装实验室设备,实验室成套设备厂家,校园功能室设备,智慧书法教室方案 - 东莞市惠森教学设备有限公司 | 雪花制冰机(实验室雪花制冰机)百科 | 农产品溯源系统_农产品质量安全追溯系统_溯源系统 | 河南膏药贴牌-膏药代加工-膏药oem厂家-洛阳今世康医药科技有限公司 | 气动机械手-搬运机械手-气动助力机械手-山东精瑞自动化设备有限公司 | 中药二氧化硫测定仪,食品二氧化硫测定仪|俊腾百科 | 热熔胶网膜|pes热熔网膜价格|eva热熔胶膜|热熔胶膜|tpu热熔胶膜厂家-苏州惠洋胶粘制品有限公司 | 炒货机-炒菜机-炒酱机-炒米机@霍氏机械 | 复合肥,化肥厂,复合肥批发,化肥代理,复合肥品牌-红四方 | 大型冰雕-景区冰雕展制作公司,3D创意设计源头厂家-[赛北冰雕] | 电缆桥架生产厂家_槽式/梯式_热镀锌线槽_广东东莞雷正电气 | 煤矿支护网片_矿用勾花菱形网_缝管式_管缝式锚杆-邯郸市永年区志涛工矿配件有限公司 | 上海瑶恒实业有限公司|消防泵泵|离心泵|官网 | 托盘租赁_塑料托盘租赁_托盘出租_栈板出租_青岛托盘租赁-优胜必达 | 纯化水设备-EDI-制药-实验室-二级反渗透-高纯水|超纯水设备 | 重庆中专|职高|技校招生-重庆中专招生网 | 合肥风管加工厂-安徽螺旋/不锈钢风管-通风管道加工厂家-安徽风之范 | 旋片真空泵_真空泵_水环真空泵_真空机组-深圳恒才机电设备有限公司 | 上海办公室装修公司_办公室设计_直营办公装修-羚志悦装 | 重庆磨床过滤机,重庆纸带过滤机,机床伸缩钣金,重庆机床钣金护罩-重庆达鸿兴精密机械制造有限公司 | 深圳市源和塑胶电子有限公司-首页 | 欧洲MV日韩MV国产_人妻无码一区二区三区免费_少妇被 到高潮喷出白浆av_精品少妇自慰到喷水AV网站 | 湖南印刷厂|长沙印刷公司|画册印刷|挂历印刷|台历印刷|杂志印刷-乐成印刷 |