成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Java內存模型的原理以及其用法是什么-創(chuàng)新互聯(lián)

Java內存模型的原理以及其用法是什么,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

創(chuàng)新互聯(lián)公司是一家集網站建設,銅梁企業(yè)網站建設,銅梁品牌網站建設,網站定制,銅梁網站建設報價,網絡營銷,網絡優(yōu)化,銅梁網站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網站。

為什么要有內存模型

在介紹 Java 內存模型之前,我們先來看一下到底什么是計算機內存模型,然后再來看 Java 內存模型在計算機內存模型的基礎上都做了哪些事情。

要說計算機的內存模型,就要說一段古老的歷史,看一下為什么要有內存模型。

內存模型:英文名 Memory Model,它是一個老古董了。它是與計算機硬件有關的一個概念。那么,我先介紹下它和硬件到底有啥關系。

CPU 和緩存一致性

我們應該知道,計算機在執(zhí)行程序的時候,每條指令都是在 CPU 中執(zhí)行的,而執(zhí)行的時候,又免不了和數(shù)據(jù)打交道。

而計算機上面的數(shù)據(jù),是存放在主存當中的,也就是計算機的物理內存。

剛開始,還相安無事,但是隨著 CPU 技術的發(fā)展,CPU 的執(zhí)行速度越來越快。

而由于內存的技術并沒有太大的變化,所以從內存中讀取和寫入數(shù)據(jù)的過程和 CPU 的執(zhí)行速度比起來差距就會越來越大,這就導致 CPU 每次操作內存都要耗費很多等待時間。

這就像一家創(chuàng)業(yè)公司,剛開始,創(chuàng)始人和員工之間工作關系其樂融融,但是隨著創(chuàng)始人的能力和野心越來越大,逐漸和員工之間出現(xiàn)了差距,普通員工越來越跟不上 CEO 的腳步。

老板的每一個命令,傳達到基層員工之后,由于基層員工的理解能力、執(zhí)行能力的欠缺,就會耗費很多時間。這也就無形中拖慢了整家公司的工作效率。

可是,不能因為內存的讀寫速度慢,就不發(fā)展 CPU 技術了吧?總不能讓內存成為計算機處理的瓶頸吧?

所以,人們想出來了一個好的辦法,就是在 CPU 和內存之間增加高速緩存。

緩存的概念大家都知道,就是保存一份數(shù)據(jù)拷貝。它的特點是速度快,內存小,并且價格昂貴。

那么,程序的執(zhí)行過程就變成了:程序在運行過程中,會將運算需要的數(shù)據(jù)從主存復制一份到 CPU 的高速緩存當中。

那么 CPU 進行計算時就可以直接從它的高速緩存讀取數(shù)據(jù)和向其中寫入數(shù)據(jù),當運算結束之后,再將高速緩存中的數(shù)據(jù)刷新到主存當中。

之后,這家公司開始設立中層管理人員,管理人員直接歸 CEO 領導,領導有什么指示,直接告訴管理人員,然后就可以去做自己的事情了。管理人員負責去協(xié)調底層員工的工作。

因為管理人員是了解手下的人員以及自己負責的事情的。所以大多數(shù)時候,公司的各種決策,通知等,CEO 只要和管理人員之間溝通就夠了。

而隨著 CPU 能力的不斷提升,一層緩存就慢慢的無法滿足要求了,就逐漸的衍生出多級緩存。

按照數(shù)據(jù)讀取順序和與 CPU 結合的緊密程度,CPU 緩存可以分為一級緩存(L1),二級緩存(L2),部分高端 CPU 還具有三級緩存(L3),每一級緩存中所儲存的全部數(shù)據(jù)都是下一級緩存的一部分。

這三種緩存的技術難度和制造成本是相對遞減的,所以其容量也是相對遞增的。

那么,在有了多級緩存之后,程序的執(zhí)行就變成了:當 CPU 要讀取一個數(shù)據(jù)時,首先從一級緩存中查找,如果沒有找到再從二級緩存中查找,如果還是沒有就從三級緩存或內存中查找。

隨著公司越來越大,老板要管的事情越來越多,公司的管理部門開始改革,開始出現(xiàn)高層,中層,底層等管理者。一級一級之間逐層管理。

單核 CPU 只含有一套 L1,L2,L3 緩存;如果 CPU 含有多個核心,即多核 CPU,則每個核心都含有一套 L1(甚至和 L2)緩存,而共享 L3(或者和 L2)緩存。

公司也分很多種,有些公司只有一個大 Boss,他一個人說了算。但是有些公司有比如聯(lián)席總經理、合伙人等機制。

單核 CPU 就像一家公司只有一個老板,所有命令都來自于他,那么就只需要一套管理班底就夠了。

多核 CPU 就像一家公司是由多個合伙人共同創(chuàng)辦的,那么,就需要給每個合伙人都設立一套供自己直接領導的高層管理人員,多個合伙人共享使用的是公司的底層員工。

還有的公司,不斷壯大,開始拆分出各個子公司。各個子公司就是多個 CPU 了,互相之前沒有共用的資源?;ゲ挥绊憽?/p>

下圖為一個單 CPU 雙核的緩存結構:

Java內存模型的原理以及其用法是什么

隨著計算機能力不斷提升,開始支持多線程。那么問題就來了,我們分別來分析下單線程、多線程在單核 CPU、多核 CPU 中的影響。

單線程:CPU 核心的緩存只被一個線程訪問。緩存獨占,不會出現(xiàn)訪問沖突等問題。

單核 CPU,多線程:進程中的多個線程會同時訪問進程中的共享數(shù)據(jù),CPU 將某塊內存加載到緩存后,不同線程在訪問相同的物理地址的時候,都會映射到相同的緩存位置,這樣即使發(fā)生線程的切換,緩存仍然不會失效。

但由于任何時刻只能有一個線程在執(zhí)行,因此不會出現(xiàn)緩存訪問沖突。

多核 CPU,多線程:每個核都至少有一個 L1  緩存。多個線程訪問進程中的某個共享內存,且這多個線程分別在不同的核心上執(zhí)行,則每個核心都會在各自的 Cache 中保留一份共享內存的緩沖。

由于多核是可以并行的,可能會出現(xiàn)多個線程同時寫各自的緩存的情況,而各自的 Cache 之間的數(shù)據(jù)就有可能不同。

在 CPU 和主存之間增加緩存,在多線程場景下就可能存在緩存一致性問題,也就是說,在多核 CPU 中,每個核的自己的緩存中,關于同一個數(shù)據(jù)的緩存內容可能不一致。

如果這家公司的命令都是串行下發(fā)的話,那么就沒有任何問題。

如果這家公司的命令都是并行下發(fā)的話,并且這些命令都是由同一個 CEO 下發(fā)的,這種機制是也沒有什么問題。因為他的命令執(zhí)行者只有一套管理體系。

如果這家公司的命令都是并行下發(fā)的話,并且這些命令是由多個合伙人下發(fā)的,這就有問題了。

因為每個合伙人只會把命令下達給自己直屬的管理人員,而多個管理人員管理的底層員工可能是公用的。

比如,合伙人 1 要辭退員工 a,合伙人 2 要給員工 a 升職,升職后的話他再被辭退需要多個合伙人開會決議。兩個合伙人分別把命令下發(fā)給了自己的管理人員。

合伙人 1 命令下達后,管理人員 a 在辭退了員工后,他就知道這個員工被開除了。

而合伙人 2 的管理人員 2 這時候在沒得到消息之前,還認為員工 a 是在職的,他就欣然的接收了合伙人給他的升職 a 的命令。

Java內存模型的原理以及其用法是什么

處理器優(yōu)化和指令重排

上面提到在 CPU 和主存之間增加緩存,在多線程場景下會存在緩存一致性問題。

除了這種情況,還有一種硬件問題也比較重要。那就是為了使處理器內部的運算單元能夠被充分利用,處理器可能會對輸入代碼進行亂序執(zhí)行處理。這就是處理器優(yōu)化。

除了現(xiàn)在很多流行的處理器會對代碼進行優(yōu)化亂序處理,很多編程語言的編譯器也會有類似的優(yōu)化,比如 Java 虛擬機的即時編譯器(JIT)也會做指令重排。

可想而知,如果任由處理器優(yōu)化和編譯器對指令重排的話,就可能導致各種各樣的問題。

關于員工組織調整的情況,如果允許人事部在接到多個命令后進行隨意拆分亂序執(zhí)行或者重排的話,那么對于這個員工以及這家公司的影響是非常大的。

并發(fā)編程的問題

前面說的和硬件有關的概念你可能聽得有點蒙,還不知道他到底和軟件有啥關系。

但是關于并發(fā)編程的問題你應該有所了解了,比如原子性問題,可見性問題和有序性問題。

其實,原子性問題,可見性問題和有序性問題是人們抽象定義出來的。而這個抽象的底層問題就是前面提到的緩存一致性問題、處理器優(yōu)化問題和指令重排問題等。

這里簡單回顧下這三個問題,我們說,并發(fā)編程,為了保證數(shù)據(jù)的安全,需要滿足以下三個特性:

原子性,是指在一個操作中,CPU 不可以在中途暫停然后再調度,即不被中斷操作,要不執(zhí)行完成,要不就不執(zhí)行。

可見性,是指當多個線程訪問同一個變量時,一個線程修改了這個變量的值,其他線程能夠立即看得到修改的值。

有序性,即程序執(zhí)行的順序按照代碼的先后順序執(zhí)行。

有沒有發(fā)現(xiàn),緩存一致性問題其實就是可見性問題。而處理器優(yōu)化是可以導致原子性問題的。指令重排即會導致有序性問題。

所以,后文將不再提起硬件層面的那些概念,而是直接使用大家熟悉的原子性、可見性和有序性。

什么是內存模型

前面提到的,緩存一致性問題、處理器優(yōu)化的指令重排問題是硬件的不斷升級導致的。那么,有沒有什么機制可以很好的解決上面的這些問題呢?

最簡單直接的做法就是廢除處理器和處理器的優(yōu)化技術、廢除 CPU 緩存,讓 CPU 直接和主存交互。

但是,這么做雖然可以保證多線程下的并發(fā)問題。但是,這就有點因噎廢食了。

所以,為了保證并發(fā)編程中可以滿足原子性、可見性及有序性。有一個重要的概念,那就是——內存模型。

為了保證共享內存的正確性(可見性、有序性、原子性),內存模型定義了共享內存系統(tǒng)中多線程程序讀寫操作行為的規(guī)范。

通過這些規(guī)則來規(guī)范對內存的讀寫操作,從而保證指令執(zhí)行的正確性。它與處理器有關、與緩存有關、與并發(fā)有關、與編譯器也有關。

它解決了 CPU 多級緩存、處理器優(yōu)化、指令重排等導致的內存訪問問題,保證了并發(fā)場景下的一致性、原子性和有序性。

內存模型解決并發(fā)問題主要采用兩種方式:

限制處理器優(yōu)化

使用內存屏障

本文就不深入底層原理來展開介紹了,感興趣的朋友可以自行學習。

什么是 Java 內存模型

前面介紹了計算機內存模型,這是解決多線程場景下并發(fā)問題的一個重要規(guī)范。

那么具體的實現(xiàn)是如何的呢?不同的編程語言,在實現(xiàn)上可能有所不同。

我們知道,Java 程序是需要運行在 Java 虛擬機上面的,Java 內存模型(Java Memory Model,JMM)就是一種符合內存模型規(guī)范的,屏蔽了各種硬件和操作系統(tǒng)的訪問差異的,保證了 Java 程序在各種平臺下對內存的訪問都能保證效果一致的機制及規(guī)范。

提到 Java 內存模型,一般指的是 JDK 5 開始使用的新內存模型,主要由 JSR-133:JavaTM Memory Model and Thread Specification 描述。

感興趣的可以參看下這份PDF文檔:

http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf

Java 內存模型規(guī)定了所有的變量都存儲在主內存中,每條線程還有自己的工作內存。

線程的工作內存中保存了該線程中用到的變量的主內存副本拷貝,線程對變量的所有操作都必須在工作內存中進行,而不能直接讀寫主內存。

不同的線程之間也無法直接訪問對方工作內存中的變量,線程間變量的傳遞均需要自己的工作內存和主存之間進行數(shù)據(jù)同步進行。

而 JMM 就作用于工作內存和主存之間數(shù)據(jù)同步過程。它規(guī)定了如何做數(shù)據(jù)同步以及什么時候做數(shù)據(jù)同步。

Java內存模型的原理以及其用法是什么

這里面提到的主內存和工作內存,讀者可以簡單的類比成計算機內存模型中的主存和緩存的概念。

特別需要注意的是,主內存和工作內存與 JVM 內存結構中的 Java 堆、棧、方法區(qū)等并不是同一個層次的內存劃分,無法直接類比。

《深入理解Java虛擬機》中認為:如果一定要勉強對應起來的話,從變量、主內存、工作內存的定義來看,主內存主要對應于 Java 堆中的對象實例數(shù)據(jù)部分。而工作內存則對應于虛擬機棧中的部分區(qū)域。

所以,再來總結下,JMM 是一種規(guī)范,是解決由于多線程通過共享內存進行通信時,存在的本地內存數(shù)據(jù)不一致、編譯器會對代碼指令重排序、處理器會對代碼亂序執(zhí)行等帶來的問題。

目的是保證并發(fā)編程場景中的原子性、可見性和有序性。

Java 內存模型的實現(xiàn)

了解 Java 多線程的朋友都知道,在 Java 中提供了一系列和并發(fā)處理相關的關鍵字,比如 Volatile、Synchronized、Final、Concurren 包等。

其實這些就是 Java 內存模型封裝了底層的實現(xiàn)后提供給程序員使用的一些關鍵字。

在開發(fā)多線程的代碼的時候,我們可以直接使用 Synchronized 等關鍵字來控制并發(fā),這樣就不需要關心底層的編譯器優(yōu)化、緩存一致性等問題。

所以,Java 內存模型,除了定義了一套規(guī)范,還提供了一系列原語,封裝了底層實現(xiàn)后,供開發(fā)者直接使用。

我們前面提到,并發(fā)編程要解決原子性、有序性和一致性的問題。下面我們就再來看下,在 Java 中,分別使用什么方式來保證。

原子性

在 Java 中,為了保證原子性,提供了兩個高級的字節(jié)碼指令 Monitorenter 和 Monitorexit。

在 Synchronized 的實現(xiàn)原理文章中,介紹過,這兩個字節(jié)碼,在 Java 中對應的關鍵字就是 Synchronized。

因此,在 Java 中可以使用 Synchronized 來保證方法和代碼塊內的操作是原子性的。

可見性

Java 內存模型是通過在變量修改后將新值同步回主內存,在變量讀取前從主內存刷新變量值的這種依賴主內存作為傳遞媒介的方式來實現(xiàn)的。

Java 中的 Volatile 關鍵字提供了一個功能,那就是被其修飾的變量在被修改后可以立即同步到主內存。

被其修飾的變量在每次使用之前都從主內存刷新。因此,可以使用 Volatile 來保證多線程操作時變量的可見性。

除了 Volatile,Java 中的 Synchronized 和 Final 兩個關鍵字也可以實現(xiàn)可見性。只不過實現(xiàn)方式不同,這里不再展開了。

有序性

在 Java 中,可以使用 Synchronized 和 Volatile 來保證多線程之間操作的有序性。

實現(xiàn)方式有所區(qū)別:Volatile 關鍵字會禁止指令重排。Synchronized 關鍵字保證同一時刻只允許一條線程操作。

好了,這里簡單的介紹完了 Java 并發(fā)編程中解決原子性、可見性以及有序性可以使用的關鍵字。

讀者可能發(fā)現(xiàn)了,好像 Synchronized 關鍵字是萬能的,它可以同時滿足以上三種特性,這也是很多人濫用 Synchronized 的原因。

但是 Synchronized 是比較影響性能的,雖然編譯器提供了很多鎖優(yōu)化技術,但是也不建議過度使用。

關于Java內存模型的原理以及其用法是什么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注創(chuàng)新互聯(lián)-成都網站建設公司行業(yè)資訊頻道了解更多相關知識。

當前文章:Java內存模型的原理以及其用法是什么-創(chuàng)新互聯(lián)
路徑分享:http://jinyejixie.com/article4/dcphie.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供云服務器網站制作、靜態(tài)網站、網站營銷App設計、面包屑導航

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都網站建設公司
乌什县| 双江| 安阳市| 故城县| 中阳县| 两当县| 贵溪市| 安化县| 山阳县| 宽甸| 灌云县| 通许县| 白玉县| 康乐县| 扎囊县| 台东县| 绿春县| 敦煌市| 治县。| 安丘市| 稷山县| 杭锦后旗| 盘锦市| 伊春市| 黄龙县| 万盛区| 尤溪县| 镇巴县| 祁门县| 留坝县| 抚松县| 咸宁市| 城步| 金乡县| 时尚| 浙江省| 织金县| 金秀| 故城县| 汉沽区| 乐亭县|