国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

如何使用 volatile, synchronized, final 進行線程間通信

keithxiaoy / 643人閱讀

摘要:如線程執行后,線程執行,相當于線程向線程發送了消息。我們可以利用這種互斥性來進行線程間通信。

你是否真正理解并會用volatile, synchronized, final進行線程間通信呢,如果你不能回答下面的幾個問題,那就說明你并沒有真正的理解:

volatile變量的操作一定具有原子性嗎?

synchronized所謂的加鎖,鎖住的是什么?

final定義的變量不變的到底是什么?

java內存模型 內存模型

看java內存模型之前,我們先來看看什么是內存模型?

在多處理器系統中,處理器通常有多級緩存,因為這些緩存離處理器更近并且可以存儲一部分數據,所以緩存可以改善處理器獲取數據的速度和減少對共享內存數據總線的占用。緩存雖然能極大的提高性能,但是同時也帶來了諸多挑戰。例如,當兩個處理器同時操作同一個內存地址的時候,該如何處理?這兩個處理器在什么條件下才能看到相同的值?

對于處理器而言,一個內存模型就是定義一些充分必要的規范,這些規范使得其他處理器對內存的寫操作對當前處理器可見,或者當前處理器的寫操作對其他處理器可見。

其他處理器對內存的寫一定發生在當前處理器對同一內存的讀之前,稱之為其他處理器對內存的寫對當前處理器可見。
Java 內存模型

知道了內存模型,那么應該可以更好的理解java內存模型。

簡單的講,java內存模型指的就是一套規范,現在最新的規范為JSR-133。這套規范包含:

線程之間如何通過內存通信

線程之間通過什么方式通信才合法,才能得到期望的結果

Java 內存模型中的內存結構

我們已經知道 java 內存模型就是一套規范,那么在這套規范中,規定的內存結構是什么樣的呢?

簡單的講,Java 內存模型將內存分為共享內存和本地內存。共享內存又稱為堆內存,指的就是線程之間共享的內存,包含所有的實例域、靜態域和數組元素。每個線程都有一個私有的,只對自己可見的內存,稱之為本地內存。

java內存模型中的內存結構如下圖所示:

共享內存中共享變量雖然由所有的線程共享,但是為了提高效率,線程并不直接使用這些變量,每個線程都會在自己的本地內存中存儲一個共享內存的副本,使用這個副本參與運算。由于這個副本的參與,導致了線程之間對共享內存的讀寫存在可見性問題。

為了方便線程之間的通信,java 提供了 volatile, synchronized, final 三個關鍵字供我們使用,下面我們來看看如何使用它們進行線程間通信

volatile

volatile 定義的變量,特殊性在于:

一個線程對 volatile 變量的寫一定對之后對這個變量的讀的線程可見。

等價于

一個線程對 volatile 變量的讀一定能看見在它之前最后一個線程對這個變量的寫。

為了實現這些語義,Java 規定,(1)當一個線程要使用共享內存中的 volatile 變量時,如圖中的變量a,它會直接從主內存中讀取,而不使用自己本地內存中的副本。(2)當一個線程對一個 volatile 變量進行寫時,它會將這個共享變量的值刷新到共享內存中。

我們可以看到,其實 volatile 變量保證的是一個線程對它的寫會立即刷新到主內存中,并置其它線程的副本為無效,它并不保證對 volatile 變量的操作都是具有原子性的。

由于

 public void add(){
     a++;         #1
 } 

等價于

 public void add() {
    temp = a;        
    temp = temp +1;  
    a = temp;         
 } 

代碼1并不是一個原子操作,所以類似于 a++ 這樣的操作會導致并發數據問題。

volatile 變量的寫可以被之后其他線程的讀看到,因此我們可以利用它進行線程間的通信。如

volatile int a;

public void set(int b) {
    a = b; 
}

public void get() {
    int i = a; 
}

線程A執行set()后,線程B執行get(),相當于線程A向線程B發送了消息。

synchronized

如果我們非要使用 a++ 這種復合操作進行線程間通信呢?java 為我們提供了synchronized。

 public synchronized void add() {
    a++; 
 }

synchronized 使得

它作用范圍內的代碼對于不同線程是互斥的,并且線程在釋放鎖的時候會將共享變量的值刷新到共享內存中。

我們可以利用這種互斥性來進行線程間通信。看下面的代碼,

public synchronized void add() {
    a++; 
}

public synchronized void get() {
    int i = a; 
}

當線程A執行 add(),線程B調用get(),由于互斥性,線程A執行完add()后,線程B才能開始執行get(),并且線程A執行完add(),釋放鎖的時候,會將a的值刷新到共享內存中。因此線程B拿到的a的值是線程A更新之后的。

volatile 和 synchronized比較

根據以上的分析,我們可以發現volatile和synchronized有些相似。

當線程對 volatile變量寫時,java 會把值刷新到共享內存中;而對于synchronized,指的是當線程釋放鎖的時候,會將共享變量的值刷新到主內存中。

線程讀取volatile變量時,會將本地內存中的共享變量置為無效;對于synchronized來說,當線程獲取鎖時,會將當前線程本地內存中的共享變量置為無效。

synchronized 擴大了可見影響的范圍,擴大到了synchronized作用的代碼塊。

final 變量

final關鍵字可以作用于變量、方法和類,我們這里只看final 變量。

final變量的特殊之處在于,

final 變量一經初始化,就不能改變其值。

這里的值對于一個對象或者數組來說指的是這個對象或者數組的引用地址。因此,一個線程定義了一個final變量之后,其他任意線程都拿到這個變量。但有一點需要注意的是,當這個final變量為對象或者數組時,

雖然我們不能講這個變量賦值為其他對象或者數組,但是我們可以改變對象的域或者數組中的元素。

線程對這個對象變量的域或者數據的元素的改變不具有線程可見性。

總結

有時候,我們在學習一門技術過程中,并不能僅僅局限于怎么用,知道怎么用之后,我們應該深入的探究一下,為什么這么用之后就能得到我們想要的結果呢?既要知其然,更要知其所以然。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65519.html

相關文章

  • Java內存模型

    摘要:內存模型對內存模型的介紹對內存模型的結構圖的線程之間的通信是通過共享內存的方式進行隱式通信,即線程把某狀態寫入主內存中的共享變量,線程讀取的值,這樣就完成了通信。 Java內存模型(JMM) 1.對內存模型的介紹 ①對Java內存模型的結構圖 java的線程之間的通信是通過共享內存的方式進行隱式通信,即線程A把某狀態寫入主內存中的共享變量X,線程B讀取X的值,這樣就完成了通信。是一種...

    sherlock221 評論0 收藏0
  • 并發編程基礎知識二

    摘要:進入方法線程停止關鍵字雖然擁有多個線程之間的可見性,但是卻不具備原子性關鍵字用于針對多個線程可變的變量操作,但是不能替代關鍵字的同步功能。 volatile關鍵字的作用是變量在多個線程之間可見volatile的作用是強制線程到主內存(共享內存)里讀取變量,而不是線程工作內存區里去讀取變量,從而實現了多個線程之間的變量可見,也就是滿足線程安全的可見性。 private volat...

    CKJOKER 評論0 收藏0
  • 慕課網_《細說Java多線程之內存可見性》學習總結

    時間:2017年07月09日星期日說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學源碼:無學習源碼:https://github.com/zccodere/s... 第一章:課程簡介 1-1 課程簡介 課程目標和學習內容 共享變量在線程間的可見性 synchronized實現可見性 volatile實現可見性 指令重排序 as-if-seria...

    wupengyu 評論0 收藏0
  • bat等大公司常考java多線程面試題

    摘要:典型地,和被用在等待另一個線程產生的結果的情形測試發現結果還沒有產生后,讓線程阻塞,另一個線程產生了結果后,調用使其恢復。使當前線程放棄當前已經分得的時間,但不使當前線程阻塞,即線程仍處于可執行狀態,隨時可能再次分得時間。 1、說說進程,線程,協程之間的區別 簡而言之,進程是程序運行和資源分配的基本單位,一個程序至少有一個進程,一個進程至少有一個線程.進程在執行過程中擁有獨立的內存單元...

    Charlie_Jade 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<