国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

(二)線程------線程通信原理JMM模型

2019-11-06 06:05:56
字體:
來源:轉載
供稿:網友

簡述:

    上一篇文章中我們學習了java的內存模型,那么現(xiàn)在我們思考一個問題:如果程序中存在多個線程,他們是怎么進行數(shù)據(jù)通信的呢?OK,帶著這個問題我們來學習本節(jié)內容---線程通信原理。    本篇博文主要講解:     ① 什么是可見性、原子性、有序性。     ② JMM模型。

JMM簡介:

     JMM:Java Memory Model(Java內存模型),圍繞著在并發(fā)過程中如何處理可見性、原子性、有序性這三個特性而建立的模型。OK,我們看一下三種特征。    原子性(atomicity): 原子性是指一個操作不能被打斷,要么全部執(zhí)行完畢,要么不執(zhí)行。在這點上有點類似于事務操作,要么全部執(zhí)行成功,要么回退到執(zhí)行該操作之前的狀態(tài) 。由Java內存模型來直接保證原子性變量操作包括read, load, assign, use, store和write。大致可以認為基本數(shù)據(jù)類型的訪問讀寫是具有原子性的。如果應用場景需要一個更大范圍的原子性保證,Java內存模型還提供了lock和unlock操作來滿足需求,盡管虛擬機沒有把lock和unlock操作直接開放給用戶使用,但是卻提供了更高層次的字節(jié)碼指令monitorenter和monitorexit來隱式地使用這兩個操作,這兩個字節(jié)碼指令反映到Java代碼中就是同步塊——synchronized關鍵字,因此在synchronized塊之間的操作也具備原子性。    可見性(visibility): 可見性是指當一個線程修改了共享變量的值,其他線程能夠立即得知這個修改。Java內存模型是通過在變量修改后將新值同步到主內存,無論是普通變量還是volatile變量都是如此,普通變量與volatile變量的區(qū)別是,volatile的特殊規(guī)則保證了新值能立即同步到主內存,以及每次使用前立即從主內存刷新。因此,可以說volatile保證了多線程操作時變量的可見性,而普通變量不能保證這一點。    除了volatile之外,Java還有兩個關鍵字能實現(xiàn)可見性,即synchronized和final。同步塊的可見性是由“對一個變量執(zhí)行unlock操作之前,必須先把此變量同步回主內存中”這條規(guī)則獲得的,而final關鍵字的可見性是指:被final修飾的字段在構造器中一旦初始化完成,并且構造器沒有把"this"的引用傳遞出去(this引用逃逸是一件很危險的事情,其他線程有可能通過這個引用訪問到“初始化了一半”的對象),那在其他線程中就能看見final字段的值。    有序性: Java程序天然的有序性可以總結為一句話:如果本線程內觀察,所有的操作都是有序的;如果在一個線程中觀察另一個線程,所有的操作都是無序的。前半句是指“線程內表現(xiàn)為串行的語義”,后半句是指“指令重排序”現(xiàn)象和“工作內存與主內存同步延遲”現(xiàn)象。JMM模型提供了volatile和synchronized來保證線程之間操作的有序性。    總之,JMM模型就是提供一套機制來保證操作的原子性、可見性和有序性。根據(jù)數(shù)據(jù)是否被線程可見將JVM將內存組織為主內存和工作內存兩個部分。主內存中主要包括本地方法區(qū)和堆。每個線程都有一個工作內存,工作內存中主要包括兩個部分,一個是屬于該線程的棧和對主存部分變量拷貝的寄存器:                       通過上面一張圖我們清晰的分析線程1與線程2通信實際上通過主內存(Main Memory)實現(xiàn)的。比如,線程1自己工作線程內存(Working Memory)中的變量int a的副本刷新到主內存,然后線程2先將自己工作內存中的變量副本置為無效再從主內存中重新獲取變量副本的值,這樣就實現(xiàn)了兩個線程間的通信。這也就是線程間通信的原理。下面在詳細說一下主內存和工作內存:主內存和工作內存:  Java內存模型的主要目標是定義程序中各個變量的訪問規(guī)則,即在JVM中將變量存儲到內存和從內存中取出變量這樣的底層細節(jié)。此處的變量與Java編程里面的變量有所不同步,它包含了實例字段、靜態(tài)字段和構成數(shù)組對象的元素,但不包含局部變量和方法參數(shù),因為后者是線程私有的,不會共享,當然不存在數(shù)據(jù)競爭問題(如果局部變量是一個reference引用類型,它引用的對象在Java堆中可被各個線程共享,但是reference引用本身在Java棧的局部變量表中,是線程私有的)。為了獲得較高的執(zhí)行效能,Java內存模型并沒有限制執(zhí)行引起使用處理器的特定寄存器或者緩存來和主內存進行交互,也沒有限制即時編譯器進行調整代碼執(zhí)行順序這類優(yōu)化措施。  JMM規(guī)定了所有的變量都存儲在主內存(Main Memory)中。每個線程還有自己的工作內存(Working Memory),線程的工作內存中保存了該線程使用到的變量的主內存的副本拷貝,線程對變量的所有操作(讀取、賦值等)都必須在工作內存中進行,而不能直接讀寫主內存中的變量(volatile變量仍然有工作內存的拷貝,但是由于它特殊的操作順序性規(guī)定,所以看起來如同直接在主內存中讀寫訪問一般)。不同的線程之間也無法直接訪問對方工作內存中的變量,線程之間值的傳遞都需要通過主內存來完成。

總結:

    ① 線程間通信是通過共享主內存的方式去實現(xiàn)的。    ② 線程間對共享數(shù)據(jù)操作時必須具備原子性、可見性和有序性。    ③ 為了保證對主內存操作數(shù)據(jù)時不同步也為了操作的方便性,Java提供了Synchronized保證操作的原子性、可見性和有序性。提供了volatile可以保證操作的可見性。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 荣成市| 巴中市| 吴忠市| 隆德县| 体育| 周口市| 泌阳县| 贵定县| 九江市| 建瓯市| 腾冲县| 达州市| 拉萨市| 芮城县| 沁阳市| 巫溪县| 贵定县| 三门峡市| 盐亭县| 孙吴县| 民勤县| 南雄市| 长宁县| 北辰区| 赤壁市| 白银市| 吉林市| 绵阳市| 宣汉县| 防城港市| 聂荣县| 庆云县| 濮阳县| 休宁县| 安徽省| 宽甸| 长泰县| 安福县| 廉江市| 祥云县| 博野县|