'java多線程深入瞭解Java內存模型與volatile含義'

"

ava多線程--深入瞭解Java內存模型與volatile含義

介紹volatile的含義之前,我們先了解下Java的內存模型,我們的應用程序在執行的時候,計算在CPU中,數據存儲在內存中,但是實際上CPU的計算能力遠遠超過了內存的存取速度,為了更好配合CPU的處理速度,在CPU與內存之間增加一個高速緩存,CPU只從Cache中獲取數據。這樣的話,就會存在一個問題,Memory中的數據與Cache中數據存在一致性的問題。

"

ava多線程--深入瞭解Java內存模型與volatile含義

介紹volatile的含義之前,我們先了解下Java的內存模型,我們的應用程序在執行的時候,計算在CPU中,數據存儲在內存中,但是實際上CPU的計算能力遠遠超過了內存的存取速度,為了更好配合CPU的處理速度,在CPU與內存之間增加一個高速緩存,CPU只從Cache中獲取數據。這樣的話,就會存在一個問題,Memory中的數據與Cache中數據存在一致性的問題。

java多線程深入瞭解Java內存模型與volatile含義

針對這種數據不一致性的問題,目前的解決方案就是通過緩存一致性協議來解決。主要思想就是當CPU寫數據時,如果該變量是共享變量,就是這個變量也存在其他CPU中,那麼就會去通知其他CPU該變量在Cahce中緩存無效了,當其他CPU要讀取這個變量的時候,發現變量狀態無效,就會到內存中讀取。

Java內存模型

Java虛擬機規範定義一種Java內存模型(Java Memory Model,JMM)來屏蔽掉硬件環境帶來的差異,確保java程序能夠正常運行在多個平臺上。

JMM規定:

所有的變量必須存在主內存中,每個線程都有自身的工作內存。

工作內存保存了主內存中所有變量的拷貝,線程對這些變量操作都在自身線程中完成,不能直接讀寫主內存。

線程之間無法訪問對方工作內存中內容,線程之間變量傳遞需要在工作內存和主存之間傳遞,都必須經過主內存。

"

ava多線程--深入瞭解Java內存模型與volatile含義

介紹volatile的含義之前,我們先了解下Java的內存模型,我們的應用程序在執行的時候,計算在CPU中,數據存儲在內存中,但是實際上CPU的計算能力遠遠超過了內存的存取速度,為了更好配合CPU的處理速度,在CPU與內存之間增加一個高速緩存,CPU只從Cache中獲取數據。這樣的話,就會存在一個問題,Memory中的數據與Cache中數據存在一致性的問題。

java多線程深入瞭解Java內存模型與volatile含義

針對這種數據不一致性的問題,目前的解決方案就是通過緩存一致性協議來解決。主要思想就是當CPU寫數據時,如果該變量是共享變量,就是這個變量也存在其他CPU中,那麼就會去通知其他CPU該變量在Cahce中緩存無效了,當其他CPU要讀取這個變量的時候,發現變量狀態無效,就會到內存中讀取。

Java內存模型

Java虛擬機規範定義一種Java內存模型(Java Memory Model,JMM)來屏蔽掉硬件環境帶來的差異,確保java程序能夠正常運行在多個平臺上。

JMM規定:

所有的變量必須存在主內存中,每個線程都有自身的工作內存。

工作內存保存了主內存中所有變量的拷貝,線程對這些變量操作都在自身線程中完成,不能直接讀寫主內存。

線程之間無法訪問對方工作內存中內容,線程之間變量傳遞需要在工作內存和主存之間傳遞,都必須經過主內存。

java多線程深入瞭解Java內存模型與volatile含義

JMM規範定義了線程工作內存與主存之間的存儲關係之後,還要保證在併發編程環境下的原子性,可見性,有序性

原子性

在Java語言,對基本數據類型的變量的讀取和賦值操作是原子性操作,即這些操作是不可被中斷的,要麼執行,要麼不執行。說說對這句話的理解,以下圖為例:

"

ava多線程--深入瞭解Java內存模型與volatile含義

介紹volatile的含義之前,我們先了解下Java的內存模型,我們的應用程序在執行的時候,計算在CPU中,數據存儲在內存中,但是實際上CPU的計算能力遠遠超過了內存的存取速度,為了更好配合CPU的處理速度,在CPU與內存之間增加一個高速緩存,CPU只從Cache中獲取數據。這樣的話,就會存在一個問題,Memory中的數據與Cache中數據存在一致性的問題。

java多線程深入瞭解Java內存模型與volatile含義

針對這種數據不一致性的問題,目前的解決方案就是通過緩存一致性協議來解決。主要思想就是當CPU寫數據時,如果該變量是共享變量,就是這個變量也存在其他CPU中,那麼就會去通知其他CPU該變量在Cahce中緩存無效了,當其他CPU要讀取這個變量的時候,發現變量狀態無效,就會到內存中讀取。

Java內存模型

Java虛擬機規範定義一種Java內存模型(Java Memory Model,JMM)來屏蔽掉硬件環境帶來的差異,確保java程序能夠正常運行在多個平臺上。

JMM規定:

所有的變量必須存在主內存中,每個線程都有自身的工作內存。

工作內存保存了主內存中所有變量的拷貝,線程對這些變量操作都在自身線程中完成,不能直接讀寫主內存。

線程之間無法訪問對方工作內存中內容,線程之間變量傳遞需要在工作內存和主存之間傳遞,都必須經過主內存。

java多線程深入瞭解Java內存模型與volatile含義

JMM規範定義了線程工作內存與主存之間的存儲關係之後,還要保證在併發編程環境下的原子性,可見性,有序性

原子性

在Java語言,對基本數據類型的變量的讀取和賦值操作是原子性操作,即這些操作是不可被中斷的,要麼執行,要麼不執行。說說對這句話的理解,以下圖為例:

java多線程深入瞭解Java內存模型與volatile含義

以這四個語句為例,其中具備原子性的語句是哪一個呢?如果說全部都是的話,可能對Java原子性的含義理解不夠,要理解“對基本數據類型的變量的讀取和賦值操作是原子性操作”,也就說讀取與賦值才是原子性的,其他均不是。也就是隻有x=1是原子性。x++,需要讀取x的值然後+1,然後再賦值回x中。y=x,需要讀取x的值,複製到y中,y++與x++一樣,以上語句都是多個賦值與讀取語句組合而成。

所以可以通過synchronized和Lock來實現,對語句和代碼塊的原子性。由於synchronized和Lock能夠保證任一時刻只有一個線程執行該代碼塊,這樣也就保證了原子性。

可見性

可見性是指當多個線程訪問同一個變量時,一旦出現某一個線程修改了這個變量的值,那麼其他線程能夠立即看得到修改的值。java中使用volatile關鍵字來保證可見性。其主要原理:一個變量被volatile修飾的時候,它的變化立即會更新到主存中,其他線程讀取該變量的時候就會去主存中讀取,類似與緩存一致性的原理。這裡看出volatile不具備鎖的功能,只是告訴線程,一旦變量變化,要去主存中讀取

有序性

在Java內存模型中,允許編譯器和處理器對指令進行重排序,指令重排主要是能夠確保執行速度更快,但是重排序過程不會影響到單線程程序的執行,但是在多線程併發執行過程就會有影響。如下圖:

"

ava多線程--深入瞭解Java內存模型與volatile含義

介紹volatile的含義之前,我們先了解下Java的內存模型,我們的應用程序在執行的時候,計算在CPU中,數據存儲在內存中,但是實際上CPU的計算能力遠遠超過了內存的存取速度,為了更好配合CPU的處理速度,在CPU與內存之間增加一個高速緩存,CPU只從Cache中獲取數據。這樣的話,就會存在一個問題,Memory中的數據與Cache中數據存在一致性的問題。

java多線程深入瞭解Java內存模型與volatile含義

針對這種數據不一致性的問題,目前的解決方案就是通過緩存一致性協議來解決。主要思想就是當CPU寫數據時,如果該變量是共享變量,就是這個變量也存在其他CPU中,那麼就會去通知其他CPU該變量在Cahce中緩存無效了,當其他CPU要讀取這個變量的時候,發現變量狀態無效,就會到內存中讀取。

Java內存模型

Java虛擬機規範定義一種Java內存模型(Java Memory Model,JMM)來屏蔽掉硬件環境帶來的差異,確保java程序能夠正常運行在多個平臺上。

JMM規定:

所有的變量必須存在主內存中,每個線程都有自身的工作內存。

工作內存保存了主內存中所有變量的拷貝,線程對這些變量操作都在自身線程中完成,不能直接讀寫主內存。

線程之間無法訪問對方工作內存中內容,線程之間變量傳遞需要在工作內存和主存之間傳遞,都必須經過主內存。

java多線程深入瞭解Java內存模型與volatile含義

JMM規範定義了線程工作內存與主存之間的存儲關係之後,還要保證在併發編程環境下的原子性,可見性,有序性

原子性

在Java語言,對基本數據類型的變量的讀取和賦值操作是原子性操作,即這些操作是不可被中斷的,要麼執行,要麼不執行。說說對這句話的理解,以下圖為例:

java多線程深入瞭解Java內存模型與volatile含義

以這四個語句為例,其中具備原子性的語句是哪一個呢?如果說全部都是的話,可能對Java原子性的含義理解不夠,要理解“對基本數據類型的變量的讀取和賦值操作是原子性操作”,也就說讀取與賦值才是原子性的,其他均不是。也就是隻有x=1是原子性。x++,需要讀取x的值然後+1,然後再賦值回x中。y=x,需要讀取x的值,複製到y中,y++與x++一樣,以上語句都是多個賦值與讀取語句組合而成。

所以可以通過synchronized和Lock來實現,對語句和代碼塊的原子性。由於synchronized和Lock能夠保證任一時刻只有一個線程執行該代碼塊,這樣也就保證了原子性。

可見性

可見性是指當多個線程訪問同一個變量時,一旦出現某一個線程修改了這個變量的值,那麼其他線程能夠立即看得到修改的值。java中使用volatile關鍵字來保證可見性。其主要原理:一個變量被volatile修飾的時候,它的變化立即會更新到主存中,其他線程讀取該變量的時候就會去主存中讀取,類似與緩存一致性的原理。這裡看出volatile不具備鎖的功能,只是告訴線程,一旦變量變化,要去主存中讀取

有序性

在Java內存模型中,允許編譯器和處理器對指令進行重排序,指令重排主要是能夠確保執行速度更快,但是重排序過程不會影響到單線程程序的執行,但是在多線程併發執行過程就會有影響。如下圖:

java多線程深入瞭解Java內存模型與volatile含義

在多線程環境,加入初始化x=1;那麼在多線程環境下,就2個線程運行條件下,無法保證x最後是1還是2。因為執行順序無法確定。

"

ava多線程--深入瞭解Java內存模型與volatile含義

介紹volatile的含義之前,我們先了解下Java的內存模型,我們的應用程序在執行的時候,計算在CPU中,數據存儲在內存中,但是實際上CPU的計算能力遠遠超過了內存的存取速度,為了更好配合CPU的處理速度,在CPU與內存之間增加一個高速緩存,CPU只從Cache中獲取數據。這樣的話,就會存在一個問題,Memory中的數據與Cache中數據存在一致性的問題。

java多線程深入瞭解Java內存模型與volatile含義

針對這種數據不一致性的問題,目前的解決方案就是通過緩存一致性協議來解決。主要思想就是當CPU寫數據時,如果該變量是共享變量,就是這個變量也存在其他CPU中,那麼就會去通知其他CPU該變量在Cahce中緩存無效了,當其他CPU要讀取這個變量的時候,發現變量狀態無效,就會到內存中讀取。

Java內存模型

Java虛擬機規範定義一種Java內存模型(Java Memory Model,JMM)來屏蔽掉硬件環境帶來的差異,確保java程序能夠正常運行在多個平臺上。

JMM規定:

所有的變量必須存在主內存中,每個線程都有自身的工作內存。

工作內存保存了主內存中所有變量的拷貝,線程對這些變量操作都在自身線程中完成,不能直接讀寫主內存。

線程之間無法訪問對方工作內存中內容,線程之間變量傳遞需要在工作內存和主存之間傳遞,都必須經過主內存。

java多線程深入瞭解Java內存模型與volatile含義

JMM規範定義了線程工作內存與主存之間的存儲關係之後,還要保證在併發編程環境下的原子性,可見性,有序性

原子性

在Java語言,對基本數據類型的變量的讀取和賦值操作是原子性操作,即這些操作是不可被中斷的,要麼執行,要麼不執行。說說對這句話的理解,以下圖為例:

java多線程深入瞭解Java內存模型與volatile含義

以這四個語句為例,其中具備原子性的語句是哪一個呢?如果說全部都是的話,可能對Java原子性的含義理解不夠,要理解“對基本數據類型的變量的讀取和賦值操作是原子性操作”,也就說讀取與賦值才是原子性的,其他均不是。也就是隻有x=1是原子性。x++,需要讀取x的值然後+1,然後再賦值回x中。y=x,需要讀取x的值,複製到y中,y++與x++一樣,以上語句都是多個賦值與讀取語句組合而成。

所以可以通過synchronized和Lock來實現,對語句和代碼塊的原子性。由於synchronized和Lock能夠保證任一時刻只有一個線程執行該代碼塊,這樣也就保證了原子性。

可見性

可見性是指當多個線程訪問同一個變量時,一旦出現某一個線程修改了這個變量的值,那麼其他線程能夠立即看得到修改的值。java中使用volatile關鍵字來保證可見性。其主要原理:一個變量被volatile修飾的時候,它的變化立即會更新到主存中,其他線程讀取該變量的時候就會去主存中讀取,類似與緩存一致性的原理。這裡看出volatile不具備鎖的功能,只是告訴線程,一旦變量變化,要去主存中讀取

有序性

在Java內存模型中,允許編譯器和處理器對指令進行重排序,指令重排主要是能夠確保執行速度更快,但是重排序過程不會影響到單線程程序的執行,但是在多線程併發執行過程就會有影響。如下圖:

java多線程深入瞭解Java內存模型與volatile含義

在多線程環境,加入初始化x=1;那麼在多線程環境下,就2個線程運行條件下,無法保證x最後是1還是2。因為執行順序無法確定。

java多線程深入瞭解Java內存模型與volatile含義

但是可以通過synchronized和Lock來保證有序性,很顯然,synchronized和Lock保證每個時刻是有一個線程執行同步代碼,相當於是讓線程順序執行同步代碼,自然就保證了有序性。

volatile關鍵字的底層原理

一個變量被volatile修飾之後,在多線程環境下,一旦有一個線程將這個變量做了修改,就會同步到主存中,那麼其他線程在獲取的時候,都會從主存中讀取。這個是如何實現的呢?

“觀察加入volatile關鍵字和沒有加入volatile關鍵字時所生成的彙編代碼發現,加入volatile關鍵字時,會多出一個lock前綴指令”這個是《深入理解Java虛擬機》中的一句話。lock前綴指令實際上相當於一個內存屏障。它意味著:

1)該指令不會發生重排序。確保指令重排序時不會把其後面的指令排到內存屏障之前的位置,也不會把前面的指令排到內存屏障的後面。比如下圖:

"

ava多線程--深入瞭解Java內存模型與volatile含義

介紹volatile的含義之前,我們先了解下Java的內存模型,我們的應用程序在執行的時候,計算在CPU中,數據存儲在內存中,但是實際上CPU的計算能力遠遠超過了內存的存取速度,為了更好配合CPU的處理速度,在CPU與內存之間增加一個高速緩存,CPU只從Cache中獲取數據。這樣的話,就會存在一個問題,Memory中的數據與Cache中數據存在一致性的問題。

java多線程深入瞭解Java內存模型與volatile含義

針對這種數據不一致性的問題,目前的解決方案就是通過緩存一致性協議來解決。主要思想就是當CPU寫數據時,如果該變量是共享變量,就是這個變量也存在其他CPU中,那麼就會去通知其他CPU該變量在Cahce中緩存無效了,當其他CPU要讀取這個變量的時候,發現變量狀態無效,就會到內存中讀取。

Java內存模型

Java虛擬機規範定義一種Java內存模型(Java Memory Model,JMM)來屏蔽掉硬件環境帶來的差異,確保java程序能夠正常運行在多個平臺上。

JMM規定:

所有的變量必須存在主內存中,每個線程都有自身的工作內存。

工作內存保存了主內存中所有變量的拷貝,線程對這些變量操作都在自身線程中完成,不能直接讀寫主內存。

線程之間無法訪問對方工作內存中內容,線程之間變量傳遞需要在工作內存和主存之間傳遞,都必須經過主內存。

java多線程深入瞭解Java內存模型與volatile含義

JMM規範定義了線程工作內存與主存之間的存儲關係之後,還要保證在併發編程環境下的原子性,可見性,有序性

原子性

在Java語言,對基本數據類型的變量的讀取和賦值操作是原子性操作,即這些操作是不可被中斷的,要麼執行,要麼不執行。說說對這句話的理解,以下圖為例:

java多線程深入瞭解Java內存模型與volatile含義

以這四個語句為例,其中具備原子性的語句是哪一個呢?如果說全部都是的話,可能對Java原子性的含義理解不夠,要理解“對基本數據類型的變量的讀取和賦值操作是原子性操作”,也就說讀取與賦值才是原子性的,其他均不是。也就是隻有x=1是原子性。x++,需要讀取x的值然後+1,然後再賦值回x中。y=x,需要讀取x的值,複製到y中,y++與x++一樣,以上語句都是多個賦值與讀取語句組合而成。

所以可以通過synchronized和Lock來實現,對語句和代碼塊的原子性。由於synchronized和Lock能夠保證任一時刻只有一個線程執行該代碼塊,這樣也就保證了原子性。

可見性

可見性是指當多個線程訪問同一個變量時,一旦出現某一個線程修改了這個變量的值,那麼其他線程能夠立即看得到修改的值。java中使用volatile關鍵字來保證可見性。其主要原理:一個變量被volatile修飾的時候,它的變化立即會更新到主存中,其他線程讀取該變量的時候就會去主存中讀取,類似與緩存一致性的原理。這裡看出volatile不具備鎖的功能,只是告訴線程,一旦變量變化,要去主存中讀取

有序性

在Java內存模型中,允許編譯器和處理器對指令進行重排序,指令重排主要是能夠確保執行速度更快,但是重排序過程不會影響到單線程程序的執行,但是在多線程併發執行過程就會有影響。如下圖:

java多線程深入瞭解Java內存模型與volatile含義

在多線程環境,加入初始化x=1;那麼在多線程環境下,就2個線程運行條件下,無法保證x最後是1還是2。因為執行順序無法確定。

java多線程深入瞭解Java內存模型與volatile含義

但是可以通過synchronized和Lock來保證有序性,很顯然,synchronized和Lock保證每個時刻是有一個線程執行同步代碼,相當於是讓線程順序執行同步代碼,自然就保證了有序性。

volatile關鍵字的底層原理

一個變量被volatile修飾之後,在多線程環境下,一旦有一個線程將這個變量做了修改,就會同步到主存中,那麼其他線程在獲取的時候,都會從主存中讀取。這個是如何實現的呢?

“觀察加入volatile關鍵字和沒有加入volatile關鍵字時所生成的彙編代碼發現,加入volatile關鍵字時,會多出一個lock前綴指令”這個是《深入理解Java虛擬機》中的一句話。lock前綴指令實際上相當於一個內存屏障。它意味著:

1)該指令不會發生重排序。確保指令重排序時不會把其後面的指令排到內存屏障之前的位置,也不會把前面的指令排到內存屏障的後面。比如下圖:

java多線程深入瞭解Java內存模型與volatile含義

比如flag=true這個語句,一定會在語句1,語句2之後(不管語句1和語句2的執行順序),一定會在語句4,語句5之後(不管語句4和語句5順序)

2)它會強制將對緩存的修改操作立即寫入主存,這是在彙編指令這一級就規定的了;

3)如果是寫操作,它會導致其他CPU中對應的緩存行無效,這樣的話,在CPU讀取的時候,一定要去主存中獲取數據

總結

1.java內存模型內容。

2.併發編程的原子性,可見性,有序性。對指令重排需要重點理解

3.volatile修飾變量,確保修改之後,其他線程能夠知道。

最後呢,給大家分享一波福利,Java從入門到精通的資料和100套項目,大家領取了之後,抓緊時間好好學習,爭取能找到好的工作,滿意的薪資:

獲取方式:

1.轉發關注小編;

2.私信小編”學習“來進行獲取。。

3.大家持續關注小編,小編每天都會更新文章,更新干貨。

"

ava多線程--深入瞭解Java內存模型與volatile含義

介紹volatile的含義之前,我們先了解下Java的內存模型,我們的應用程序在執行的時候,計算在CPU中,數據存儲在內存中,但是實際上CPU的計算能力遠遠超過了內存的存取速度,為了更好配合CPU的處理速度,在CPU與內存之間增加一個高速緩存,CPU只從Cache中獲取數據。這樣的話,就會存在一個問題,Memory中的數據與Cache中數據存在一致性的問題。

java多線程深入瞭解Java內存模型與volatile含義

針對這種數據不一致性的問題,目前的解決方案就是通過緩存一致性協議來解決。主要思想就是當CPU寫數據時,如果該變量是共享變量,就是這個變量也存在其他CPU中,那麼就會去通知其他CPU該變量在Cahce中緩存無效了,當其他CPU要讀取這個變量的時候,發現變量狀態無效,就會到內存中讀取。

Java內存模型

Java虛擬機規範定義一種Java內存模型(Java Memory Model,JMM)來屏蔽掉硬件環境帶來的差異,確保java程序能夠正常運行在多個平臺上。

JMM規定:

所有的變量必須存在主內存中,每個線程都有自身的工作內存。

工作內存保存了主內存中所有變量的拷貝,線程對這些變量操作都在自身線程中完成,不能直接讀寫主內存。

線程之間無法訪問對方工作內存中內容,線程之間變量傳遞需要在工作內存和主存之間傳遞,都必須經過主內存。

java多線程深入瞭解Java內存模型與volatile含義

JMM規範定義了線程工作內存與主存之間的存儲關係之後,還要保證在併發編程環境下的原子性,可見性,有序性

原子性

在Java語言,對基本數據類型的變量的讀取和賦值操作是原子性操作,即這些操作是不可被中斷的,要麼執行,要麼不執行。說說對這句話的理解,以下圖為例:

java多線程深入瞭解Java內存模型與volatile含義

以這四個語句為例,其中具備原子性的語句是哪一個呢?如果說全部都是的話,可能對Java原子性的含義理解不夠,要理解“對基本數據類型的變量的讀取和賦值操作是原子性操作”,也就說讀取與賦值才是原子性的,其他均不是。也就是隻有x=1是原子性。x++,需要讀取x的值然後+1,然後再賦值回x中。y=x,需要讀取x的值,複製到y中,y++與x++一樣,以上語句都是多個賦值與讀取語句組合而成。

所以可以通過synchronized和Lock來實現,對語句和代碼塊的原子性。由於synchronized和Lock能夠保證任一時刻只有一個線程執行該代碼塊,這樣也就保證了原子性。

可見性

可見性是指當多個線程訪問同一個變量時,一旦出現某一個線程修改了這個變量的值,那麼其他線程能夠立即看得到修改的值。java中使用volatile關鍵字來保證可見性。其主要原理:一個變量被volatile修飾的時候,它的變化立即會更新到主存中,其他線程讀取該變量的時候就會去主存中讀取,類似與緩存一致性的原理。這裡看出volatile不具備鎖的功能,只是告訴線程,一旦變量變化,要去主存中讀取

有序性

在Java內存模型中,允許編譯器和處理器對指令進行重排序,指令重排主要是能夠確保執行速度更快,但是重排序過程不會影響到單線程程序的執行,但是在多線程併發執行過程就會有影響。如下圖:

java多線程深入瞭解Java內存模型與volatile含義

在多線程環境,加入初始化x=1;那麼在多線程環境下,就2個線程運行條件下,無法保證x最後是1還是2。因為執行順序無法確定。

java多線程深入瞭解Java內存模型與volatile含義

但是可以通過synchronized和Lock來保證有序性,很顯然,synchronized和Lock保證每個時刻是有一個線程執行同步代碼,相當於是讓線程順序執行同步代碼,自然就保證了有序性。

volatile關鍵字的底層原理

一個變量被volatile修飾之後,在多線程環境下,一旦有一個線程將這個變量做了修改,就會同步到主存中,那麼其他線程在獲取的時候,都會從主存中讀取。這個是如何實現的呢?

“觀察加入volatile關鍵字和沒有加入volatile關鍵字時所生成的彙編代碼發現,加入volatile關鍵字時,會多出一個lock前綴指令”這個是《深入理解Java虛擬機》中的一句話。lock前綴指令實際上相當於一個內存屏障。它意味著:

1)該指令不會發生重排序。確保指令重排序時不會把其後面的指令排到內存屏障之前的位置,也不會把前面的指令排到內存屏障的後面。比如下圖:

java多線程深入瞭解Java內存模型與volatile含義

比如flag=true這個語句,一定會在語句1,語句2之後(不管語句1和語句2的執行順序),一定會在語句4,語句5之後(不管語句4和語句5順序)

2)它會強制將對緩存的修改操作立即寫入主存,這是在彙編指令這一級就規定的了;

3)如果是寫操作,它會導致其他CPU中對應的緩存行無效,這樣的話,在CPU讀取的時候,一定要去主存中獲取數據

總結

1.java內存模型內容。

2.併發編程的原子性,可見性,有序性。對指令重排需要重點理解

3.volatile修飾變量,確保修改之後,其他線程能夠知道。

最後呢,給大家分享一波福利,Java從入門到精通的資料和100套項目,大家領取了之後,抓緊時間好好學習,爭取能找到好的工作,滿意的薪資:

獲取方式:

1.轉發關注小編;

2.私信小編”學習“來進行獲取。。

3.大家持續關注小編,小編每天都會更新文章,更新干貨。

java多線程深入瞭解Java內存模型與volatile含義
"

ava多線程--深入瞭解Java內存模型與volatile含義

介紹volatile的含義之前,我們先了解下Java的內存模型,我們的應用程序在執行的時候,計算在CPU中,數據存儲在內存中,但是實際上CPU的計算能力遠遠超過了內存的存取速度,為了更好配合CPU的處理速度,在CPU與內存之間增加一個高速緩存,CPU只從Cache中獲取數據。這樣的話,就會存在一個問題,Memory中的數據與Cache中數據存在一致性的問題。

java多線程深入瞭解Java內存模型與volatile含義

針對這種數據不一致性的問題,目前的解決方案就是通過緩存一致性協議來解決。主要思想就是當CPU寫數據時,如果該變量是共享變量,就是這個變量也存在其他CPU中,那麼就會去通知其他CPU該變量在Cahce中緩存無效了,當其他CPU要讀取這個變量的時候,發現變量狀態無效,就會到內存中讀取。

Java內存模型

Java虛擬機規範定義一種Java內存模型(Java Memory Model,JMM)來屏蔽掉硬件環境帶來的差異,確保java程序能夠正常運行在多個平臺上。

JMM規定:

所有的變量必須存在主內存中,每個線程都有自身的工作內存。

工作內存保存了主內存中所有變量的拷貝,線程對這些變量操作都在自身線程中完成,不能直接讀寫主內存。

線程之間無法訪問對方工作內存中內容,線程之間變量傳遞需要在工作內存和主存之間傳遞,都必須經過主內存。

java多線程深入瞭解Java內存模型與volatile含義

JMM規範定義了線程工作內存與主存之間的存儲關係之後,還要保證在併發編程環境下的原子性,可見性,有序性

原子性

在Java語言,對基本數據類型的變量的讀取和賦值操作是原子性操作,即這些操作是不可被中斷的,要麼執行,要麼不執行。說說對這句話的理解,以下圖為例:

java多線程深入瞭解Java內存模型與volatile含義

以這四個語句為例,其中具備原子性的語句是哪一個呢?如果說全部都是的話,可能對Java原子性的含義理解不夠,要理解“對基本數據類型的變量的讀取和賦值操作是原子性操作”,也就說讀取與賦值才是原子性的,其他均不是。也就是隻有x=1是原子性。x++,需要讀取x的值然後+1,然後再賦值回x中。y=x,需要讀取x的值,複製到y中,y++與x++一樣,以上語句都是多個賦值與讀取語句組合而成。

所以可以通過synchronized和Lock來實現,對語句和代碼塊的原子性。由於synchronized和Lock能夠保證任一時刻只有一個線程執行該代碼塊,這樣也就保證了原子性。

可見性

可見性是指當多個線程訪問同一個變量時,一旦出現某一個線程修改了這個變量的值,那麼其他線程能夠立即看得到修改的值。java中使用volatile關鍵字來保證可見性。其主要原理:一個變量被volatile修飾的時候,它的變化立即會更新到主存中,其他線程讀取該變量的時候就會去主存中讀取,類似與緩存一致性的原理。這裡看出volatile不具備鎖的功能,只是告訴線程,一旦變量變化,要去主存中讀取

有序性

在Java內存模型中,允許編譯器和處理器對指令進行重排序,指令重排主要是能夠確保執行速度更快,但是重排序過程不會影響到單線程程序的執行,但是在多線程併發執行過程就會有影響。如下圖:

java多線程深入瞭解Java內存模型與volatile含義

在多線程環境,加入初始化x=1;那麼在多線程環境下,就2個線程運行條件下,無法保證x最後是1還是2。因為執行順序無法確定。

java多線程深入瞭解Java內存模型與volatile含義

但是可以通過synchronized和Lock來保證有序性,很顯然,synchronized和Lock保證每個時刻是有一個線程執行同步代碼,相當於是讓線程順序執行同步代碼,自然就保證了有序性。

volatile關鍵字的底層原理

一個變量被volatile修飾之後,在多線程環境下,一旦有一個線程將這個變量做了修改,就會同步到主存中,那麼其他線程在獲取的時候,都會從主存中讀取。這個是如何實現的呢?

“觀察加入volatile關鍵字和沒有加入volatile關鍵字時所生成的彙編代碼發現,加入volatile關鍵字時,會多出一個lock前綴指令”這個是《深入理解Java虛擬機》中的一句話。lock前綴指令實際上相當於一個內存屏障。它意味著:

1)該指令不會發生重排序。確保指令重排序時不會把其後面的指令排到內存屏障之前的位置,也不會把前面的指令排到內存屏障的後面。比如下圖:

java多線程深入瞭解Java內存模型與volatile含義

比如flag=true這個語句,一定會在語句1,語句2之後(不管語句1和語句2的執行順序),一定會在語句4,語句5之後(不管語句4和語句5順序)

2)它會強制將對緩存的修改操作立即寫入主存,這是在彙編指令這一級就規定的了;

3)如果是寫操作,它會導致其他CPU中對應的緩存行無效,這樣的話,在CPU讀取的時候,一定要去主存中獲取數據

總結

1.java內存模型內容。

2.併發編程的原子性,可見性,有序性。對指令重排需要重點理解

3.volatile修飾變量,確保修改之後,其他線程能夠知道。

最後呢,給大家分享一波福利,Java從入門到精通的資料和100套項目,大家領取了之後,抓緊時間好好學習,爭取能找到好的工作,滿意的薪資:

獲取方式:

1.轉發關注小編;

2.私信小編”學習“來進行獲取。。

3.大家持續關注小編,小編每天都會更新文章,更新干貨。

java多線程深入瞭解Java內存模型與volatile含義
java多線程深入瞭解Java內存模型與volatile含義
"

ava多線程--深入瞭解Java內存模型與volatile含義

介紹volatile的含義之前,我們先了解下Java的內存模型,我們的應用程序在執行的時候,計算在CPU中,數據存儲在內存中,但是實際上CPU的計算能力遠遠超過了內存的存取速度,為了更好配合CPU的處理速度,在CPU與內存之間增加一個高速緩存,CPU只從Cache中獲取數據。這樣的話,就會存在一個問題,Memory中的數據與Cache中數據存在一致性的問題。

java多線程深入瞭解Java內存模型與volatile含義

針對這種數據不一致性的問題,目前的解決方案就是通過緩存一致性協議來解決。主要思想就是當CPU寫數據時,如果該變量是共享變量,就是這個變量也存在其他CPU中,那麼就會去通知其他CPU該變量在Cahce中緩存無效了,當其他CPU要讀取這個變量的時候,發現變量狀態無效,就會到內存中讀取。

Java內存模型

Java虛擬機規範定義一種Java內存模型(Java Memory Model,JMM)來屏蔽掉硬件環境帶來的差異,確保java程序能夠正常運行在多個平臺上。

JMM規定:

所有的變量必須存在主內存中,每個線程都有自身的工作內存。

工作內存保存了主內存中所有變量的拷貝,線程對這些變量操作都在自身線程中完成,不能直接讀寫主內存。

線程之間無法訪問對方工作內存中內容,線程之間變量傳遞需要在工作內存和主存之間傳遞,都必須經過主內存。

java多線程深入瞭解Java內存模型與volatile含義

JMM規範定義了線程工作內存與主存之間的存儲關係之後,還要保證在併發編程環境下的原子性,可見性,有序性

原子性

在Java語言,對基本數據類型的變量的讀取和賦值操作是原子性操作,即這些操作是不可被中斷的,要麼執行,要麼不執行。說說對這句話的理解,以下圖為例:

java多線程深入瞭解Java內存模型與volatile含義

以這四個語句為例,其中具備原子性的語句是哪一個呢?如果說全部都是的話,可能對Java原子性的含義理解不夠,要理解“對基本數據類型的變量的讀取和賦值操作是原子性操作”,也就說讀取與賦值才是原子性的,其他均不是。也就是隻有x=1是原子性。x++,需要讀取x的值然後+1,然後再賦值回x中。y=x,需要讀取x的值,複製到y中,y++與x++一樣,以上語句都是多個賦值與讀取語句組合而成。

所以可以通過synchronized和Lock來實現,對語句和代碼塊的原子性。由於synchronized和Lock能夠保證任一時刻只有一個線程執行該代碼塊,這樣也就保證了原子性。

可見性

可見性是指當多個線程訪問同一個變量時,一旦出現某一個線程修改了這個變量的值,那麼其他線程能夠立即看得到修改的值。java中使用volatile關鍵字來保證可見性。其主要原理:一個變量被volatile修飾的時候,它的變化立即會更新到主存中,其他線程讀取該變量的時候就會去主存中讀取,類似與緩存一致性的原理。這裡看出volatile不具備鎖的功能,只是告訴線程,一旦變量變化,要去主存中讀取

有序性

在Java內存模型中,允許編譯器和處理器對指令進行重排序,指令重排主要是能夠確保執行速度更快,但是重排序過程不會影響到單線程程序的執行,但是在多線程併發執行過程就會有影響。如下圖:

java多線程深入瞭解Java內存模型與volatile含義

在多線程環境,加入初始化x=1;那麼在多線程環境下,就2個線程運行條件下,無法保證x最後是1還是2。因為執行順序無法確定。

java多線程深入瞭解Java內存模型與volatile含義

但是可以通過synchronized和Lock來保證有序性,很顯然,synchronized和Lock保證每個時刻是有一個線程執行同步代碼,相當於是讓線程順序執行同步代碼,自然就保證了有序性。

volatile關鍵字的底層原理

一個變量被volatile修飾之後,在多線程環境下,一旦有一個線程將這個變量做了修改,就會同步到主存中,那麼其他線程在獲取的時候,都會從主存中讀取。這個是如何實現的呢?

“觀察加入volatile關鍵字和沒有加入volatile關鍵字時所生成的彙編代碼發現,加入volatile關鍵字時,會多出一個lock前綴指令”這個是《深入理解Java虛擬機》中的一句話。lock前綴指令實際上相當於一個內存屏障。它意味著:

1)該指令不會發生重排序。確保指令重排序時不會把其後面的指令排到內存屏障之前的位置,也不會把前面的指令排到內存屏障的後面。比如下圖:

java多線程深入瞭解Java內存模型與volatile含義

比如flag=true這個語句,一定會在語句1,語句2之後(不管語句1和語句2的執行順序),一定會在語句4,語句5之後(不管語句4和語句5順序)

2)它會強制將對緩存的修改操作立即寫入主存,這是在彙編指令這一級就規定的了;

3)如果是寫操作,它會導致其他CPU中對應的緩存行無效,這樣的話,在CPU讀取的時候,一定要去主存中獲取數據

總結

1.java內存模型內容。

2.併發編程的原子性,可見性,有序性。對指令重排需要重點理解

3.volatile修飾變量,確保修改之後,其他線程能夠知道。

最後呢,給大家分享一波福利,Java從入門到精通的資料和100套項目,大家領取了之後,抓緊時間好好學習,爭取能找到好的工作,滿意的薪資:

獲取方式:

1.轉發關注小編;

2.私信小編”學習“來進行獲取。。

3.大家持續關注小編,小編每天都會更新文章,更新干貨。

java多線程深入瞭解Java內存模型與volatile含義
java多線程深入瞭解Java內存模型與volatile含義
java多線程深入瞭解Java內存模型與volatile含義
"

相關推薦

推薦中...