C說話之free函數和野指針引見。本站提示廣大學習愛好者:(C說話之free函數和野指針引見)文章只能為提供參考,不一定能成為您想要的結果。以下是C說話之free函數和野指針引見正文
在JAVA中經由過程synchronized語句可以完成多線程並發。應用同步代碼塊,JVM包管統一時光只要一個線程可以具有某一對象的鎖。鎖機制完成了多個線程平安地對臨界資本停止拜訪。
同步代碼寫法以下:
代碼1:
Object obj = new Object(); ... synchronized(obj) { //TODO: 拜訪臨界資本 }
JAVA的多線程老是充斥圈套,假如我們用Boolean作為被同步的對象,能夠會湧現以下兩種情形:
一. 認為對一個對象加鎖,現實同步的是分歧對象。
代碼2:
private volatile Boolean isTrue = false; publich void aMethod() { ... synchronized(isTrue) { isTrue = !isTrue; //TODO: 拜訪臨界資本 isTrue = !isTrue; } ... }
咋一看下面的代碼沒有成績,因為應用了synchronized(isTrue)統一時光只能有一個線程拜訪臨界資本,但現實其實不是如許。由於false和true這兩個常量對應著兩個分歧的對象。當isTrue發生變更時,極可能招致分歧的線程同步了分歧的對象。JAVA的主動裝箱會將false變成Boolean.FALSE,將true變成Boolean.TRUE(同時這也解釋了此處若將false改成Boolean.FALSE其成果也是一樣的)。寫一個以下情況的測試代碼以下:
代碼3:
public class BooleanTest { private volatile Boolean isTrue = Boolean.FALSE; //此處用false也一樣 public void aMethod() { for(int i=0;i<10;i++) { Thread t = new Thread() { public void run() { synchronized(isTrue) { isTrue = !isTrue; System.out.println(Thread.currentThread().getName() + " - isTrue=" + isTrue); try{ Double ran = 1000 * Math.random(); Thread.sleep(ran.intValue()); }catch(InterruptedException e) {} if(!isTrue) System.out.println(Thread.currentThread().getName() + " - Oh, No!"); isTrue = !isTrue; } } }; t.start(); } } public static void main(String... args) { BooleanTest bt = new BooleanTest(); bt.aMethod(); } }
運轉以上代碼,不時的會看到 " - Oh, No!",表現分歧的線程同時進入到synchronized代碼塊中。
二. 認為同步的是分歧對象,現實是一個對象。
有時刻我們能夠願望在多個對象長進行同步,假如應用了Boolean作為被同步對象,極可能會招致原來應當沒有關系的兩個同步塊應用了雷同對象的鎖。示例以下:
代碼4:
private volatile Boolean aBoolean = Boolean.FALSE; private volatile Boolean anotherBoolean = false; public void aMethod() { ... synchronized(aBoolean) { //TODO: 拜訪臨界資本1 } ... } public void anotherMethod() { ... synchronized(anotherBoolean) { //TODO: 拜訪臨界資本2 } ... }
假定本來aMethod和anotherMethod分離會被兩組沒有關系的線程挪用。然則因為Boolean.FALSE和false指向的是統一個對象,能夠招致對臨界資本2的拜訪被臨界資本1壅塞了(反之亦然)。
以上兩種情形解釋,在應用同步塊時,盡可能不消應用Boolean對象作為被同步對象,否則能夠會湧現意想不到的成績,或許對今後的代碼修正形成圈套。
從此也能夠看出,任何對常量的同步都是有風險的。假如必定要對 Boolean 停止同步,必定要用 new 操作符來創立 Boolean 對象。