2.1.5臟讀

實現(xiàn)多個線程調(diào)用同一個方法時,為避免數(shù)據(jù)出現(xiàn)交叉的情況,使用synchronized關(guān)鍵字進行同步

雖然在賦值時進行了同步,但在取值時有可能出現(xiàn)一些意想不到的意外,這種情況就是臟讀。發(fā)生臟讀的情況是在讀取實例變量時,此值已經(jīng)被其他線程更改過了。

/**
 * @author wuyoushan
 * @date 2017/4/10.
 */
public class PublicVar {
    public String username="A";
    public String password="AA";

    synchronized public void setValue(String username,String password){
        try{
            this.username=username;
            Thread.sleep(5000);
            this.password=password;
            System.out.println("setValue method thread name="+
            Thread.currentThread().getName()+" username="+
            username+" password="+password);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    public void getValue(){
        System.out.println("getValue method thread name="+
                Thread.currentThread().getName()+" username="+
                username+" password="+password);
    }
}

/**
 * @author wuyoushan
 * @date 2017/4/4.
 */
public class ThreadA extends Thread{

    private PublicVar publicVar;

    public ThreadA(PublicVar publicVar){
        super();
        this.publicVar=publicVar;
    }

    @Override
    public void run() {
        super.run();
        publicVar.setValue("B","BB");
    }
}

/**
 * @author wuyoushan
 * @date 2017/3/14.
 */
public class Test {
    public static void main(String[] args) {
       try{
           PublicVar publicVar=new PublicVar();
           ThreadA thread=new ThreadA(publicVar);
           thread.start();
            Thread.sleep(200);
           publicVar.getValue();
       }catch (InterruptedException e){
           e.printStackTrace();
       }
    }
}

程序的運行結(jié)果為:

getValue method thread name=main username=B password=AA
setValue method thread name=Thread-0 username=B password=BB

出現(xiàn)臟讀是因為public void getValue()方法并不是同步的,所以可以在任意時候進行調(diào)用。解決方法當(dāng)然就是加上同步synchronized關(guān)鍵字,代碼如下:

/**
 * @author wuyoushan
 * @date 2017/4/10.
 */
public class PublicVar {
    public String username="A";
    public String password="AA";

    synchronized public void setValue(String username,String password){
        try{
            this.username=username;
            Thread.sleep(5000);
            this.password=password;
            System.out.println("setValue method thread name="+
            Thread.currentThread().getName()+" username="+
            username+" password="+password);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    synchronized public void getValue(){
        System.out.println("getValue method thread name="+
                Thread.currentThread().getName()+" username="+
                username+" password="+password);
    }
}

程序的運行結(jié)果為:

setValue method thread name=Thread-0 username=B password=BB
getValue method thread name=main username=B password=BB

可見,方法setValue()和getValue()被依次執(zhí)行。通過這個案例不僅要知道臟讀是通過synchronized關(guān)鍵字解決的,還要知道如下內(nèi)容:

當(dāng)A線程調(diào)用anyObject對象加入synchronized關(guān)鍵字的X方法時,A線程就獲得了X方法的鎖,更準(zhǔn)確的講,是獲取了對象的鎖,所以其他線程必須等A線程執(zhí)行完畢才可以調(diào)用X方法,但B線程可以隨意調(diào)用其他的非synchronized同步方法

當(dāng)A線程調(diào)用anyObject對象加入synchronized關(guān)鍵字的X方法時,A線程就獲得了X方法的所在對象的鎖,所以其他線程必須等A線程執(zhí)行完畢才可以調(diào)用X方法,而B線程如果調(diào)用聲明了synchronized關(guān)鍵字的非X方法時,必須等A線程將X方法執(zhí)行完,也就是釋放對象鎖后才可以調(diào)用。這時A線程已經(jīng)執(zhí)行了一個完整的任務(wù),也就是說username和password這兩個實例變量已經(jīng)同時被賦值,不存在臟讀的基本環(huán)境

摘選自 java多線程核心編程技術(shù)-2.1.5

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,902評論 0 11
  • 本文出自 Eddy Wiki ,轉(zhuǎn)載請注明出處:http://eddy.wiki/interview-java.h...
    eddy_wiki閱讀 2,299評論 0 14
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,740評論 18 399
  • 簡介 本次主要介紹java多線程中的同步,也就是如何在java語言中寫出線程安全的程序。如何在java語言中解決非...
    小人物灌籃閱讀 536評論 0 1
  • 早晨六點多,天還未大亮。在冬日朦朧的氤氳中,我?guī)е赀^花甲的父親匆匆趕往醫(yī)院做檢查。 坐在公交車上,我想起父親說的...
    寶昱閱讀 273評論 0 2

友情鏈接更多精彩內(nèi)容