俗話說得好,工慾善其事必先利其器,對於Java開發者來說,簡單瞭解Java虛擬機某些特性有益於提升開發者的內功。爲什麼我們在編寫Java代碼前,需要安裝並且配置好JDK?JDK內置的這些包功能爲什麼這麼強大?爲什麼我們的程序會出現內存泄露呢?爲什麼在代碼中加入Synchronized關鍵字多線程訪問程序不會出現數據不一致問題?好多類似的問題,在我們瞭解JVM之後就會得到答案。
《深入理解Java虛擬機》 周志明著 這本書大家普遍推薦。
主要組成部分:
public class happenBeforeDemo { private int value = 0; public int getValue() { return value; } public void setValue(int value) { this.value = value; } public static void main(String[] args) { happenBeforeDemo happenBeforeDemo = new happenBeforeDemo(); new Thread(() -> happenBeforeDemo.setValue(22)).start(); new Thread(() -> System.out.println(happenBeforeDemo.getValue())).start(); } }
大家猜測下輸出的結果是什麼?0還是1?而這段代碼遵循的是什麼原則?
先行併發原則是什麼?
程序次序規則 管程鎖定規則 volatile變量規則 線程啓動規則 線程終止規則 線程中斷規則 對象終結規則 傳遞性
衡量線程安全性問題 不要受時間順序的干擾 而是一切以先行發生原則爲基準
由於第一個線程和第二個線程分別調用setValue()和getValue()兩個函數,不在同一個線程中,程序次序規則不適用,由於沒有同步塊則自然不會發生lock操作與unlock操作,管程鎖定不適合。由於value沒有添加volatile修飾,自然就沒有volatile變量規則,後面的線程啓動,線程終止,線程中斷,對象終結規則也和這裏沒有關係。最後一條傳遞性也不適用。所以該操作爲線程不安全操作。
解決方案也比較常見
/** *線程A 訪問getValue 線程B訪問setValue *解決方案 synchronized volatile */
我們知道這段代碼最終會編譯成.class文件,在我們查看字節碼之前,先了解下以下簡單的知識。
字節碼的格式說明:
1:魔術與Class文件的版本 2:常量池 3:訪問標誌 4:類索引父索引與接口索引集合 5:字段表集合 6:方法表集合 7:屬性表集合(1code 2Exceptions 3 LineNumberTable 4LocalVariableTable 5 SourceFile屬性 6ConstantValue屬性 7 InnerClasses 8 Deprecated以及Synthetic屬性 9 StackMapTable屬性(JDK1.6後加的) 10 Signature屬性(JDK1.5後加的)11 BootstrapMethods屬性(JDK1.7後加的))。。。。
更多內容關注微信公衆號