国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java多線程學(xué)習(xí)(三)volatile關(guān)鍵字

tain335 / 3184人閱讀

摘要:三關(guān)鍵字能保證原子性嗎并發(fā)編程藝術(shù)這本書上說保證但是在自增操作非原子操作上不保證,多線程編程核心藝術(shù)這本書說不保證。多線程訪問關(guān)鍵字不會發(fā)生阻塞,而關(guān)鍵字可能會發(fā)生阻塞關(guān)鍵字能保證數(shù)據(jù)的可見性,但不能保證數(shù)據(jù)的原子性。

系列文章傳送門:

Java多線程學(xué)習(xí)(一)Java多線程入門

Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1)

java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(2)

Java多線程學(xué)習(xí)(三)volatile關(guān)鍵字

Java多線程學(xué)習(xí)(四)等待/通知(wait/notify)機(jī)制

Java多線程學(xué)習(xí)(五)線程間通信知識點補(bǔ)充

Java多線程學(xué)習(xí)(六)Lock鎖的使用

Java多線程學(xué)習(xí)(七)并發(fā)編程中一些問題

系列文章將被優(yōu)先更新于微信公眾號“Java面試通關(guān)手冊”,歡迎廣大Java程序員和愛好技術(shù)的人員關(guān)注。

本節(jié)思維導(dǎo)圖:

思維導(dǎo)圖源文件+思維導(dǎo)圖軟件關(guān)注微信公眾號:“Java面試通關(guān)手冊”回復(fù)關(guān)鍵字:“Java多線程”免費領(lǐng)取。

一 簡介 先來看看維基百科對“volatile關(guān)鍵字”的定義:

在程序設(shè)計中,尤其是在C語言、C++、C#和Java語言中,使用volatile關(guān)鍵字聲明的變量或?qū)ο笸ǔ>哂信c優(yōu)化、多線程相關(guān)的特殊屬性。通常,volatile關(guān)鍵字用來阻止(偽)編譯器認(rèn)為的無法“被代碼本身”改變的代碼(變量/對象)進(jìn)行優(yōu)化。如在C語言中,volatile關(guān)鍵字可以用來提醒編譯器它后面所定義的變量隨時有可能改變,因此編譯后的程序每次需要存儲或讀取這個變量的時候,都會直接從變量地址中讀取數(shù)。如果沒有volatile關(guān)鍵字,則編譯器可能優(yōu)化讀取和存儲,可能暫時使用寄存器中的值,如果這個變量由別的程序更新了的話,將出現(xiàn)不一致的現(xiàn)象。據(jù)

在C環(huán)境中,volatile關(guān)鍵字的真實定義和適用范圍經(jīng)常被誤解。雖然C++、C#和Java都保留了C中的volatile關(guān)鍵字,但在這些編程語言中volatile的用法和語義卻大相徑庭。

Java中的“volatile關(guān)鍵字”關(guān)鍵字:

在 JDK1.2 之前,Java的內(nèi)存模型實現(xiàn)總是從主存(即共享內(nèi)存)讀取變量,是不需要進(jìn)行特別的注意的。而在當(dāng)前的 Java 內(nèi)存模型下,線程可以把變量保存本地內(nèi)存(比如機(jī)器的寄存器)中,而不是直接在主存中進(jìn)行讀寫。這就可能造成一個線程在主存中修改了一個變量的值,而另外一個線程還繼續(xù)使用它在寄存器中的變量值的拷貝,造成數(shù)據(jù)的不一致

要解決這個問題,就需要把變量聲明為 volatile,這就指示 JVM,這個變量是不穩(wěn)定的,每次使用它都到主存中進(jìn)行讀取。

二 volatile關(guān)鍵字的可見性

volatile 修飾的成員變量在每次被線程訪問時,都強(qiáng)迫從主存(共享內(nèi)存)中重讀該成員變量的值。而且,當(dāng)成員變量發(fā)生變化時,強(qiáng)迫線程將變化值回寫到主存(共享內(nèi)存)。這樣在任何時刻,兩個不同的線程總是看到某個成員變量的同一個值,這樣也就保證了同步數(shù)據(jù)的可見性

RunThread.java

 private boolean isRunning = true;
 int m;
    public boolean isRunning() {
        return isRunning;
    }
    public void setRunning(boolean isRunning) {
        this.isRunning = isRunning;
    }
    @Override
    public void run() {
        System.out.println("進(jìn)入run了");
        while (isRunning == true) {
            int a=2;
            int b=3;
            int c=a+b;
            m=c;
        }
        System.out.println(m);
        System.out.println("線程被停止了!");
    }
}

Run.java

public class Run {
    public static void main(String[] args) throws InterruptedException {
        RunThread thread = new RunThread();
        
        thread.start();
        Thread.sleep(1000);
        thread.setRunning(false);

        System.out.println("已經(jīng)賦值為false");
    }
}

運(yùn)行結(jié)果:

RunThread類中的isRunning變量沒有加上volatile關(guān)鍵字時,運(yùn)行以上代碼會出現(xiàn)死循環(huán),這是因為isRunning變量雖然被修改但是沒有被寫到主存中,這也就導(dǎo)致該線程在本地內(nèi)存中的值一直為true,這樣就導(dǎo)致了死循環(huán)的產(chǎn)生。

解決辦法也很簡單:isRunning變量前加上volatile關(guān)鍵字即可。

這樣運(yùn)行就不會出現(xiàn)死循環(huán)了。
加上volatile關(guān)鍵字后的運(yùn)行結(jié)果:

你是不是以為到這就完了?

不存在的!!!(這里還有一點需要強(qiáng)調(diào),下面的內(nèi)容一定要看,不然你在用volatile關(guān)鍵字時會很迷糊,因為書籍幾乎都沒有提這個問題)

假如你把while循環(huán)代碼里加上任意一個輸出語句或者sleep方法你會發(fā)現(xiàn)死循環(huán)也會停止,不管isRunning變量是否被加上了上volatile關(guān)鍵字。

加上輸出語句:

    while (isRunning == true) {
            int a=2;
            int b=3;
            int c=a+b;
            m=c;
            System.out.println(m);
        }

加上sleep方法:

        while (isRunning == true) {
            int a=2;
            int b=3;
            int c=a+b;
            m=c;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

這是為什么呢?

因為:JVM會盡力保證內(nèi)存的可見性,即便這個變量沒有加同步關(guān)鍵字。換句話說,只要CPU有時間,JVM會盡力去保證變量值的更新。這種與volatile關(guān)鍵字的不同在于,volatile關(guān)鍵字會強(qiáng)制的保證線程的可見性。而不加這個關(guān)鍵字,JVM也會盡力去保證可見性,但是如果CPU一直有其他的事情在處理,它也沒辦法。最開始的代碼,一直處于死循環(huán)中,CPU處于一直占用的狀態(tài),這個時候CPU沒有時間,JVM也不能強(qiáng)制要求CPU分點時間去取最新的變量值。而加了輸出或者sleep語句之后,CPU就有可能有時間去保證內(nèi)存的可見性,于是while循環(huán)可以被終止

三 volatile關(guān)鍵字能保證原子性嗎?

《Java并發(fā)編程藝術(shù)》這本書上說保證但是在自增操作(非原子操作)上不保證,《Java多線程編程核心藝術(shù)》這本書說不保證。

我個人更傾向于這種說法:volatile無法保證對變量原子性的。我個人感覺《Java并發(fā)編程藝術(shù)》這本書上說volatile關(guān)鍵字保證原子性嗎但是在自增操作(非原子操作)上不保證這種說法是有問題的。只是個人看法,希望不要被噴。可以看下面測試代碼:

MyThread.java

public class MyThread extends Thread {
    volatile public static int count;

    private static void addCount() {
        for (int i = 0; i < 100; i++) {
            count=i;
        }
        System.out.println("count=" + count);

    }
    @Override
    public void run() {
        addCount();
    }
}

Run.java

public class Run {
    public static void main(String[] args) {
        MyThread[] mythreadArray = new MyThread[100];
        for (int i = 0; i < 100; i++) {
            mythreadArray[i] = new MyThread();
        }

        for (int i = 0; i < 100; i++) {
            mythreadArray[i].start();
        }
    }

}

運(yùn)行結(jié)果:

上面的“count=i;”是一個原子操作,但是運(yùn)行結(jié)果大部分都是正確結(jié)果99,但是也有部分不是99的結(jié)果。

解決辦法

使用synchronized關(guān)鍵字加鎖。(這只是一種方法,Lock和AtomicInteger原子類都可以,因為之前學(xué)過synchronized關(guān)鍵字,所以我們使用synchronized關(guān)鍵字的方法)

修改MyThread.java如下:

public class MyThread extends Thread {
    public static int count;

    synchronized private static void addCount() {
        for (int i = 0; i < 100; i++) {
            count=i;
        }
        System.out.println("count=" + count);
    }
    @Override
    public void run() {
        addCount();
    }
}

這樣運(yùn)行輸出的count就都為99了,所以要保證數(shù)據(jù)的原子性還是要使用synchronized關(guān)鍵字

四 synchronized關(guān)鍵字和volatile關(guān)鍵字比較

volatile關(guān)鍵字是線程同步的輕量級實現(xiàn),所以volatile性能肯定比synchronized關(guān)鍵字要好。但是volatile關(guān)鍵字只能用于變量而synchronized關(guān)鍵字可以修飾方法以及代碼塊。synchronized關(guān)鍵字在JavaSE1.6之后進(jìn)行了主要包括為了減少獲得鎖和釋放鎖帶來的性能消耗而引入的偏向鎖和輕量級鎖以及其它各種優(yōu)化之后執(zhí)行效率有了顯著提升,實際開發(fā)中使用synchronized關(guān)鍵字還是更多一些

多線程訪問volatile關(guān)鍵字不會發(fā)生阻塞,而synchronized關(guān)鍵字可能會發(fā)生阻塞

volatile關(guān)鍵字能保證數(shù)據(jù)的可見性,但不能保證數(shù)據(jù)的原子性。synchronized關(guān)鍵字兩者都能保證。

volatile關(guān)鍵字用于解決變量在多個線程之間的可見性,而ynchronized關(guān)鍵字解決的是多個線程之間訪問資源的同步性。

參考:
《Java多線程編程核心技術(shù)》

《Java并發(fā)編程的藝術(shù)》

極客學(xué)院Java并發(fā)編程wiki: http://wiki.jikexueyuan.com/p...

如果你覺得博主的文章不錯,歡迎轉(zhuǎn)發(fā)點贊。你能從中學(xué)到知識就是我最大的幸運(yùn)。

歡迎關(guān)注我的微信公眾號:“Java面試通關(guān)手冊”(分享各種Java學(xué)習(xí)資源,面試題,以及企業(yè)級Java實戰(zhàn)項目回復(fù)關(guān)鍵字免費領(lǐng)取)。另外我創(chuàng)建了一個Java學(xué)習(xí)交流群(群號:174594747),歡迎大家加入一起學(xué)習(xí),這里更有面試,學(xué)習(xí)視頻等資源的分享。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/69101.html

相關(guān)文章

  • 線程學(xué)習(xí)筆記(1):volatile和synchronized

    摘要:今天開始整理學(xué)習(xí)多線程的知識,談?wù)勛钪匾膬蓚€關(guān)鍵字和。但是這樣一個過程比較慢,在使用多線程的時候就會出現(xiàn)問題。有序性有序性是指多線程執(zhí)行結(jié)果的正確性。這種機(jī)制在多線程中會出現(xiàn)問題,因此可以通過來禁止重排。 今天開始整理學(xué)習(xí)多線程的知識,談?wù)勛钪匾膬蓚€關(guān)鍵字:volatile和synchronized。 一、三個特性 1、原子性 所謂原子性操作就是指這些操作是不可中斷的,要么執(zhí)行過程...

    jk_v1 評論0 收藏0
  • JAVA線程機(jī)制解析-volatile&synchronized

    摘要:當(dāng)一個線程持有重量級鎖時,另外一個線程就會被直接踢到同步隊列中等待。 java代碼先編譯成字節(jié)碼,字節(jié)碼最后編譯成cpu指令,因此Java的多線程實現(xiàn)最終依賴于jvm和cpu的實現(xiàn) synchronized和volatile 我們先來討論一下volatile關(guān)鍵字的作用以及實現(xiàn)機(jī)制,每個線程看到的用volatile修飾的變量的值都是最新的,更深入的解釋就涉及到Java的內(nèi)存模型了,我們...

    dendoink 評論0 收藏0
  • 線程基礎(chǔ)必要知識點!看了學(xué)習(xí)線程事半功倍

    摘要:是需要我們?nèi)ヌ幚砗芏嗍虑椋瑸榱朔乐苟嗑€程給我們帶來的安全和性能的問題下面就來簡單總結(jié)一下我們需要哪些知識點來解決多線程遇到的問題。 前言 不小心就鴿了幾天沒有更新了,這個星期回家咯。在學(xué)校的日子要努力一點才行! 只有光頭才能變強(qiáng) 回顧前面: 多線程三分鐘就可以入個門了! Thread源碼剖析 本文章的知識主要參考《Java并發(fā)編程實戰(zhàn)》這本書的前4章,這本書的前4章都是講解并發(fā)的基...

    YPHP 評論0 收藏0
  • Java內(nèi)存模型中volatile的內(nèi)存語義及對同步的作用

    摘要:一接觸內(nèi)存模型中的實例靜態(tài)變量以及數(shù)組都存儲在堆內(nèi)存中,可在線程之間共享。所以,在編碼上實現(xiàn)鎖的內(nèi)存語義,可以通過對一個變量的讀寫,來實現(xiàn)線程之間相互通知,保證臨界區(qū)域代碼的互斥執(zhí)行。 原文發(fā)表于我的博客 volatile關(guān)鍵字: 使用volatile關(guān)鍵字修飾的的變量,總能看到任意線程對它最后的寫入,即總能保證任意線程在讀寫volatile修飾的變量時,總是從內(nèi)存中讀取最新的值。以下...

    QLQ 評論0 收藏0
  • Java 線程volatile 解釋

    摘要:支持多線程,中創(chuàng)建線程的方式有兩種繼承類,重寫方法。多線程編程很常見的情況下是希望多個線程共享資源,通過多個線程同時消費資源來提高效率,但是新手一不小心很容易陷入一個編碼誤區(qū)。所以,在進(jìn)行多線程編程的時候一定要留心多個線程是否共享資源。 文章首發(fā)于 http://jaychen.cc作者 JayChen showImg(https://segmentfault.com/img/remo...

    ytwman 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<