java內存模型按照線程隔離性_深入理解Java多線程與并發框(第③篇)——Java內存模型與原子性、可見性、有序性...

f1f9b2fef13680e1e2aca35e89399e15.png

一、Java內存模型

Java Memory Modle,簡稱 JMM,中文名稱 Java內存模型,它是一個抽象的概念,用來描述或者規范訪問內存變量的方式。因為各中計算機的操作系統和硬件不同,方式機制也可能不同,Java內存模型用于屏蔽(適配)各種差異,以此來達到訪問各個平臺的一致的效果。這也是Java夸平臺的重要原因之一。

主內存: Java內存規定了所有變量都存儲在主內存(Main Memory)中,各個線程又有自己的本地內存(工作內存),本地內存保存著主內存中部分變量。具體訪問方式如下:

9231860fdbef6a6526d06ca9a626acfb.png

JMM工作方式

**lock加鎖:**為了保證訪問主內存變量的線程安全性,在訪問前一般會加鎖處理;

**read讀:**從主內存中讀取一個變量到工作內存;

**load加載:**把read讀到的變量加載到工作內存的變量副本中;

**use使用:**此時線程可以使用其工作內存中的變量了;

**assign賦值:**將處理后的變量賦值給工作內存中的變量;

**store存儲:**將工作內存中的變量存儲到主內存中,以新建new 一個新變量的方式存儲;

**write寫:**將store存在的新變量的引用賦值給被處理的變量;

**unload解鎖:**所有的工作做完,最后解鎖釋放資源。

二、Java內存模型的三大特性

1. 原子性(Atomicity)

這里的原子性如同數據庫事務中是原子性,一個或多個操作要么全執行成功要么全執行失敗(全不執行)。

int a = 1;

a++;

double b = 1.5;

復制代碼

Java內存模型只保證單一的操作具有原子性,比如上面的 int a = 1; 是一個單子的操作,所以具有原子性。而 a++ 操作在底層會分為三個操作:1)、讀取a的值給臨時變量;2)、臨時變量a的值加1操作;3)、將加操作后的值賦值給a。每個操作都是原子的,但Java內存模型在多線程下并不能保證多操作具有整體原子性,因為它也不知道這個整體內有多少操作,用戶想要達到多操作具有整體原子性,需要對響應的代碼塊做同步(synchronous)處理,比如使用 有鎖的synchronized 或 無鎖的CAS。

2. 可見性(Visibility)

這里的可見性是內存可見性。

e72e5bb62e8998629322016abfc55fa8.png

如上圖,線程1和線程2在未同步的情況下對共享內存(主內存)中的變量進行訪問,比如兩個線程的操作都是對變量a進行加1操作。假設線程1首先獲取主內存中變量a的值,隨后線程2又獲取了主內存變量a的值,此時它們工作內存中a的值都是1,它們各自將a的值加1操作,然后assign至工作內存,工作內存中變量a的值都是2,然后兩個線程又將值刷新到主內存,最后的結果是主內存中變量a的值是2。雖然整體對a的值加1操作做了兩次操作,但由于線程間的操作是互相隔離的,默認情況下無法感知內存變量的值在隨后的變化,也就無法訪問內存中最新的變量值,這就是內存可行性的問題。

如何解決內存可見性的問題?

對進入臨界區的線程做同步處理(比如 synchronized),同一時刻僅有一個線程能夠訪問臨界區的資源;

使用 volatile 關鍵字保證內存可見性,它能保證訪問臨界區資源的所有線程總能看到共享資源的最新值;

CAS無鎖化。

3. 有序性(Ordering)

線程內的所有操作都是有序的,既程序執行的順序按照代碼的先后順序執行。比如下面的示例:

int a = 1;

int b = 2;

int c = a + b;

復制代碼

線程內程序會先執行 int a = 1; ,然后執行 int b = 2; 最后執行int c = a + b;。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/372212.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/372212.shtml
英文地址,請注明出處:http://en.pswp.cn/news/372212.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PHP通過PDO連接Microsoft Access數據庫

1連接到access數據庫 $db new PDO("odbc:Driver{Microsoft Access Driver (*.mdb, *.accdb)}; dbq" .realpath("yourfilepath\# ddsbbn3A02.Mdb")) or die("Connect Error"); realpath函數用來規范化絕對路徑 2修改數據庫中BM_sitelink表中字段…

ZK實際應用:樣式和布局

在之前的ZK in Action帖子中,我們使用ZK MVVM實現了CRUD功能 。 我們還快速瀏覽了一些樣式代碼,可能需要更多的解釋。 在本文中,我們將討論如何在ZK小部件上附加新CSS樣式規則,以及如何覆蓋現有樣式。 我們還將介紹ZK中UI布局的一…

java面向對象的三大特征是6_Java面向對象的三大特征

面向對象的本質:以類的方式組織代碼,以對象的方式組織數據。面向對象三大特性:封裝 繼承 多態封裝:概念:隱藏對象內部的復雜性,只對外公開簡單的接口。便于外界調用,從而提高系統的可擴展性&…

Tornado(一)

Tornado 特點 Tornado是一個用Python寫的相對簡單的、不設障礙的Web服務器架構,用以處理上萬的同時的連接口,讓實時的Web服務通暢起來。雖然跟現在的一些用Python寫的Web架構相似,比如Django,但Tornado更注重速度,能夠…

Android下Opengl ES實現單屏幕雙眼顯示

http://blog.csdn.net/u011371324/article/details/68946779 默認情況下,Opengl ES使用系統提供的幀緩沖區作為繪圖表面,一般情況下,如果只在屏幕的表面繪圖的話,系統提供的默認幀緩沖區很高效,但是很多應用程序需要渲…

Oracle Service Bus –線程阻塞案例研究

本案例研究描述了在AIX 6.1和IBM Java VM 1.6上運行的Oracle Service Bus 11g遇到的線程阻塞問題的完整根本原因分析過程。 本文也是您提高線程轉儲分析技能的絕佳機會,我強烈建議您學習并正確理解以下分析方法。 與過早的中間件(Weblogic)重…

java 可以重載等于號碼_Java面試之Java基礎4——重載與重寫的區別

目錄重載與重寫的概念重載與重寫的區別重載與重寫的總結構造器是否能被重寫override為什么函數不能根據返回類型來區分重載重載與重寫的概念重載:同樣一個方法可以根據輸入參數列表的不同,做出不同的處理。普通方法和構造器方法都能夠重載。方法重載&…

二維數組、多維數組

二維數組: 定義二維數組 int[,] myArray new int[幾個一維數組,數組中的個數]; 數組可以具有多個維度。例如,下列聲明創建一個四行兩列的二維數組(可以理解為4個1維數組,數組中包含2個元素): int[,] myArray new int[4,2]; int[…

一張大圖片有多個小圖片

這個頁面也是我看到別人的寫的,感覺不錯,就自己留下了為了以后自己可以容易找到,也希望可以方便到別人。 寫這個頁面 需要注意的是: 1.寫每一個小圖片的位置時候,要用id,這樣等級就高了,不然不起作用。 2.因…

java中如何調用dal接口案例_關于Java:接口的目的

好吧,我認為接口是一種強制對象實現一定數量功能的方法,而不必使用繼承。有點像合同。我半明白他們的意思。但是,如果界面中的所有內容都是:public interface animal{void eat(object food);}它沒有這樣的實現,那么無論…

Android Studio混淆

這一篇說一下Android Studio的代碼混淆: 第一步:要想使混淆生效,要修改項目(App)下的build.gradle一處內容:minifyEnabled 的值 設置為true,當前項目就可以使用混淆了。 apply plugin: com.and…

內存訪問模式很重要

在高性能計算中,通常會說高速緩存未命中的代價是算法的最大性能損失。 多年來,處理器速度的提高大大超過了延遲到主內存的速度。 通過更寬的多通道總線,到主內存的帶寬已大大增加,但是延遲并未顯著減少。 為了掩蓋這種延遲&#x…

上傳頭像將光標去掉

οnfοcus"this.blur();" unselectable"on" οnfοcus"this.blur();"支持火狐,谷歌等主流瀏覽器 unselectable支持ie瀏覽器轉載于:https://www.cnblogs.com/jar-gon/p/6841239.html

java底層 文件操作_JAVA的文件操作【轉】

11.3 I/O類使用由于在IO操作中,需要使用的數據源有很多,作為一個IO技術的初學者,從讀寫文件開始學習IO技術是一個比較好的選擇。因為文件是一種常見的數據源,而且讀寫文件也是程序員進行IO編程的一個基本能力。本章IO類的使用就從…

JAVA多線程,真的能提高效率嗎

舉個栗子 比如挖一個隧道,有2種開工方法1、只在山的一頭挖,直至挖到山的另一頭,從而打通隧道,這可以看成是單線程 2、在山的兩頭挖,同時開工,最后在山的中間接通,從而打通隧道,這感覺…

Java 8:測試Lambda水

Java 8大約有一年的時間了,它具有我非常期待的語言功能: Lambda Expression 。 令人遺憾的是,另一個重要功能Java平臺模塊已延遲到Java9。但是,將lambda表達式(或閉包)添加到該語言中將使Java編程變得更好。…

java定義js函數_JS中可以先使用函數,然后再定義.

首先要說明的,下面這種方式是對的,雖然不知道為什么,很奇怪為什么可以先使用,再定義,希望有了解的人可以給個說法.hello(www.openj.cn);function hello(name){alert("hello " name)};本文首發于 http://blog.openj.cn下面的這種定義函數方式,對于寫一些比較復雜的代碼…

基于閥值的工作流引擎設計

最近在做工作流處理流程部分的工作,順便研究了一下工作流引擎的一些設計理念和原理。由于以前接觸過人工智能神經網絡的一些東西,發現工作流引擎和神經網絡還是頗有一些相似之處,都是滿足一定的條件下向下一個節點傳遞。在神經網絡的神經元中…

Git之安裝管理

1.Git安裝部署 Git是分布式的版本控制系統,我們只要有了一個原始Git版本倉庫,就可以讓其他主機克隆走這個原始版本倉庫,從而使得一個Git版本倉庫可以被同時分布到不同的主機之上,并且每臺主機的版本庫都是一樣的,沒有主…

Java執行程序服務類型

ExecutorService功能是Java 5附帶的。它擴展了Executor接口,并提供了線程池功能來執行異步簡短任務。 使用Java 6提供的ExecutorService接口有五種異步執行任務的方法。 ExecutorService execService Executors.newCachedThreadPool(); 這…