[Java并发编程实战] 共享对象之可见性
2019獨角獸企業重金招聘Python工程師標準>>>
「 ***盛年不重來,一日難再晨,及時當勉勵,歲月不待人。***」 陶淵明
PS: 如果覺得本文有用的話,請幫忙點贊,留言評論支持一下哦,您的支持是我最大的動力!謝謝啦~
我們已經知道同步代碼塊和同步方法可以保證以原子的方式執行,其實,同步還有另外一個重要概念:內存可見性。換句話說,我們不僅希望防止某個線程正在使用對象狀態而另一個線程同時在修改狀態,而且希望確保當一個線程修改了對象的狀態后,其他線程能夠看到修改后的狀態。
#可見性 一個線程對共享變量值的修改,能夠及時的被其他線程看到。可見性微妙的,這是因為可能發生錯誤的事情總是與直覺大相徑庭。來看下面這個例子和他的執行結果:
public class NoVisibility {private static boolean ready;private static int number;private static class ReaderThread extends Thread {public void run() {while(!ready)Thread.yield();System.out.println(number);}}public static void main(String[] args) {// TODO Auto-generated method stubnew ReaderThread().start();number = 88;ready = true;} }上面的代碼清單,親測執行的結果是88。 然而,書本上的解釋是可能出現錯誤的結果。錯誤的結果有下面兩種情況(我重現不到下面的結果):
即可親測沒有發生,但是可能會發生。為了防止這種現象的發生,只能通過對共享變量進行恰當的同步。
####Java 內存模型(JMM,Java Memory Model) 描述了 java 程序中各種變量(線程共享變量)的訪問規則,以及在 JVM 中將變量存儲到內存和從內存中讀取出變量的底層細節。
所有變量都存儲在主內存中,每個線程都有自己獨立的工作內存,里面保存該線程使用到的變量副本,即主內存中該變量的一份拷貝。
線程對共享變量的所有操作必須在自己的工作內存,線程間變量值的傳遞需要通過主內存來完成。
####加鎖與可見性 加鎖的含義不僅僅局限于互斥行為,還包括內存可見性。為了確保所有線程都能看到共享變量的最新值,所有執行讀操作或者寫操作都必須在同一個鎖上同步。
當線程 B 執行有鎖保護的代碼塊時,可以看到線程 A 之前在同一個同步代碼塊中所有的操作結果。這就是為啥要求所有線程在同一個鎖上同步,為了確保某個線程寫入該變量的值對于其他線程來說是可見的。
####非原子的64位操作 JVM 允許將64位的讀操作或寫操作分解為兩個32位的操作。Java 中的 long 類型和 double 類型是64位的,所以當讀取一個非 volatile 類型的 long 變量時,如果該變量的讀操作和寫操作在不同的線程中執行,那么很可能會讀取到某個值的高32位和另一個值的低32位。因此,在多線程中使用共享的可變的 long 和 double 類型變量時不安全的,除非用關鍵字 volatile 來聲明他們,或者用鎖保護起來。
####volatile變量 Java 提供了一種稍弱的同步機制,即 volatile 變量,用來確保將變量的更新操作通知到其他線程。volatile 變量具有 synchronized 的可見性,但是不具備原子特性。要使 volatile 變量提供理想的線程安全,必須同時滿足下面兩個條件:
- 對變量的寫操作不依賴于自身當前值
- 該變量沒有包含在具有其他變量的不變式中
volatile 通常被當做標識完成、中斷、狀態的標記使用。典型應用如下代碼,檢查狀態標記,以確定是否退出一個循環。
volatile boolean asleep;while(!asleep)countSomeSheep();當然,上面也可以用鎖,但是會讓代碼變得復雜。volatile 變量不會加鎖,也就不會引起線程的阻塞,相比 sychronized, 這只是輕量級的同步機制。盡管 volatile 也可以用來標識其他類型的狀態信息,但是要格外小心。比如, volatile 的語義不足以使自增操作(count++)原子化。
本文原創首發于微信公眾號 [ 林里少年 ],歡迎關注第一時間獲取更新。
轉載于:https://my.oschina.net/seaicelin/blog/1823595
總結
以上是生活随笔為你收集整理的[Java并发编程实战] 共享对象之可见性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用nodejs搭建HTTPS serv
- 下一篇: MicroPython支持图形化编辑了: