歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

線程與內存交互操作

線程與內存交互操作 
 

        所有的變量(實例字段,靜態字段,構成數組對象的 元素,不包括局部變量和方法參數)都存儲在主內存中,每個線程有自己的工作內存,線程的工作內存保存被線程使用到變量的主內存副本拷貝。線程對變量的所有操作都必須在工作內存中進行,而不能直接讀寫主內存的變量。不同線程之間也不能直接訪問對方工作內存中的變量,線程間變量值的傳遞通過主內存來完成。 

Java內存模型定義了八種操作

  • lock(鎖定):作用於主內存的變量,它把一個變量標識為一個線程獨占的狀態
  • unlock(解鎖):作用於主內存的變量,它把一個處於鎖定狀態的變量釋放出來,釋放後的變量才可以被其他線程鎖定
  • read(讀取):作用於主內存的變量,它把一個變量的值從主內存傳送到線程中的工作內存,以便隨後的load動作使用
  • load(載入):作用於工作內存的變量,它把read操作從主內存中得到的變量值放入工作內存的變量副本中
  • use(使用):作用於工作內存的變量,它把工作內存中一個變量的值傳遞給執行引擎
  • assign(賦值):作用於工作內存的變量,它把一個從執行引擎接收到的值賦值給工作內存中的變量
  • store(存儲):作用於工作內存的變量,它把工作內存中的一個變量的值傳送到主內存中,以便隨後的write操作
  • write(寫入):作用於主內存的變量,它把store操作從工作內存中得到的變量的值寫入主內存的變量中

Java內存模型還規定了執行上述8種基本操作時必須滿足如下規則

    1、不允許read和load、store和write操作之一單獨出現,以上兩個操作必須按順序執行,但沒有保證必須連續執行,也就是說,read與load之間、store與write之間是可插入其他指令的。

    2、不允許一個線程丟棄它的最近的assign操作,即變量在工作內存中改變了之後必須把該變化同步回主內存。

    3、不允許一個線程無原因地(沒有發生過任何assign操作)把數據從線程的工作內存同步回主內存中。

    4、一個新的變量只能從主內存中“誕生”,不允許在工作內存中直接使用一個未被初始化(load或assign)的變量,換句話說就是對一個變量實施use和store操作之前,必須先執行過了assign和load操作。

    5、一個變量在同一個時刻只允許一條線程對其執行lock操作,但lock操作可以被同一個條線程重復執行多次,多次執行lock後,只有執行相同次數的unlock操作,變量才會被解鎖。

    6、如果對一個變量執行lock操作,將會清空工作內存中此變量的值,在執行引擎使用這個變量前,需要重新執行load或assign操作初始化變量的值。

    7、如果一個變量實現沒有被lock操作鎖定,則不允許對它執行unlock操作,也不允許去unlock一個被其他線程鎖定的變量。

   8、對一個變量執行unlock操作之前,必須先把此變量同步回主內存(執行store和write操作)。

volatile關鍵字的作用

        保證了新值能立即存儲到主內存,每次使用前立即從主內存中刷新。 
        禁止指令重排序優化。 
        注:volatile關鍵字不能保證在多線程環境下對共享數據的操作的正確性。可以使用在自己狀態改變之後需要立即通知所有線程的情況下。    

final域

        final類型的域是不能修改的,除了這一點外,在Java內存模型中,final域還有著特殊的語義,final域能確保初始化過程的安全性,從而可以不受限制地訪問不可變對象,並在共享這些對象時無須同步。具體而言,就是被final修飾的字段在構造器中一旦被初始化完成,並且構造器沒有把“this”的引用傳遞出去(this引用逃逸是一件很危險的事情,其他線程有可能通過這個引用訪問到“初始化了一半”的對象),那麼在其他線程中就能看到final字段的值,而且其外、外部可見狀態永遠也不會改變。它所帶來的安全性是最簡單最純粹的。

Copyright © Linux教程網 All Rights Reserved