<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
    數據加載中……

    Java多線程初學者指南(6):慎重使用volatile關鍵字

    本文為原創,如需轉載,請注明作者和出處,謝謝!

    上一篇:Java多線程初學者指南(5):join方法的使用

        volatile關鍵字相信了解Java多線程的讀者都很清楚它的作用。volatile關鍵字用于聲明簡單類型變量,如int、float、boolean等數據類型。如果這些簡單數據類型聲明為volatile,對它們的操作就會變成原子級別的。但這有一定的限制。例如,下面的例子中的n就不是原子級別的:

    package mythread;

    public class JoinThread extends Thread
    {
        
    public static volatile int n = 0;
        public void run()
        {
            
    for (int i = 0; i < 10; i++)
                
    try
            {
                    n 
    = n + 1;
                    sleep(
    3); // 為了使運行結果更隨機,延遲3毫秒

                }
                
    catch (Exception e)
                {
                }
        }

        
    public static void main(String[] args) throws Exception
        {

            Thread threads[] 
    = new Thread[100];
            
    for (int i = 0; i < threads.length; i++)
                
    // 建立100個線程
                threads[i] = new JoinThread();
            
    for (int i = 0; i < threads.length; i++)
                
    // 運行剛才建立的100個線程
                threads[i].start();
            
    for (int i = 0; i < threads.length; i++)
                
    // 100個線程都執行完后繼續
                threads[i].join();
            System.out.println(
    "n=" + JoinThread.n);
        }
    }

         如果對n的操作是原子級別的,最后輸出的結果應該為n=1000,而在執行上面積代碼時,很多時侯輸出的n都小于1000,這說明n=n+1不是原子級別的操作。原因是聲明為volatile的簡單變量如果當前值由該變量以前的值相關,那么volatile關鍵字不起作用,也就是說如下的表達式都不是原子操作:

    = n + 1;
    n
    ++;

          如果要想使這種情況變成原子操作,需要使用synchronized關鍵字,如上的代碼可以改成如下的形式:
    package mythread;

    public class JoinThread extends Thread
    {
        
    public static int n = 0;

        
    public static synchronized void inc()
        {
            n
    ++;
        }
        
    public void run()
        {
            
    for (int i = 0; i < 10; i++)
                
    try
                {
                    inc(); 
    // n = n + 1 改成了 inc();
                    sleep(3); // 為了使運行結果更隨機,延遲3毫秒

                }
                
    catch (Exception e)
                {
                }
        }

        
    public static void main(String[] args) throws Exception
        {

            Thread threads[] 
    = new Thread[100];
            
    for (int i = 0; i < threads.length; i++)
                
    // 建立100個線程
                threads[i] = new JoinThread();
            
    for (int i = 0; i < threads.length; i++)
                
    // 運行剛才建立的100個線程
                threads[i].start();
            
    for (int i = 0; i < threads.length; i++)
                
    // 100個線程都執行完后繼續
                threads[i].join();
            System.out.println(
    "n=" + JoinThread.n);
        }
    }

        上面的代碼將n=n+1改成了inc(),其中inc方法使用了synchronized關鍵字進行方法同步。因此,在使用volatile關鍵字時要慎重,并不是只要簡單類型變量使用volatile修飾,對這個變量的所有操作都是原來操作,當變量的值由自身的上一個決定時,如n=n+1、n++等,volatile關鍵字將失效,只有當變量的值和自身上一個值無關時對該變量的操作才是原子級別的,如n = m + 1,這個就是原級別的。所以在使用volatile關鍵時一定要謹慎,如果自己沒有把握,可以使用synchronized來代替volatile。

    下一篇:Java多線程初學者指南(7):向線程傳遞數據的三種方法
         




    Android開發完全講義(第2版)(本書版權已輸出到臺灣)

    http://product.dangdang.com/product.aspx?product_id=22741502



    Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


    新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

    posted on 2009-03-14 16:44 銀河使者 閱讀(9406) 評論(10)  編輯  收藏 所屬分類: java 原創多線程

    評論

    # re: Java多線程初學者指南(6):慎重使用volatile關鍵字  回復  更多評論   

    使用volatile關鍵字時該變量必須獨立于程序的其他內容和這個變量以前的值。
    btw:n++的動作實際由“讀,添加,寫”三個步驟組成的,并不是原子操作。
    2009-03-15 09:00 | Leo1734

    # re: Java多線程初學者指南(6):慎重使用volatile關鍵字  回復  更多評論   

    volatile的原子操作是將讀、寫合二為一了,保證了其他線程讀取變量時總是最新的,如果變量的值和自身以前的值相關,則volatile不起作用,如n++、n=n-1等。
    2009-03-15 09:19 | 銀河使者

    # re: Java多線程初學者指南(6):慎重使用volatile關鍵字  回復  更多評論   

    @Leo1734
    如果從bytecode角度看,Java源代碼級的很多操作都不是原子的,javac將其編譯成bytecode時都有多步組成。n = m也是由多步組成的,不過要給n加上volatile,n=m就是原子級的操作。
    2009-03-15 09:21 | 銀河使者

    # re: Java多線程初學者指南(6):慎重使用volatile關鍵字  回復  更多評論   

    受教了,謝謝各位
    2009-03-15 11:59 | 習習

    # re: Java多線程初學者指南(6):慎重使用volatile關鍵字[未登錄]  回復  更多評論   

    volatile是保證變量對其他線程的可見性
    2009-03-16 11:46 | jbahamut

    # re: Java多線程初學者指南(6):慎重使用volatile關鍵字  回復  更多評論   

    其實我覺得這個問題應該是線程的問題,主要是線程執行的時間可能有兩個同時獲取這個int值,然后第一個線程增加后,第二個線程在增加,覆蓋了其值,主要是線程沒有對n 這個變量加鎖,造成多個線程同時讀取相同的值
    2009-03-16 13:21 | guming123416

    # re: Java多線程初學者指南(6):慎重使用volatile關鍵字  回復  更多評論   

    @guming123416
    至于為什么volatile在某些時候不好使,這得問JVM了,可能是實現機制的問題,如果想保險點,應盡量少用volatile。thanking in java的作者也建議少用volatile。
    2009-03-16 13:52 | 銀河使者

    # re: Java多線程初學者指南(6):慎重使用volatile關鍵字  回復  更多評論   

    你上面的我兩個在JDK1.6上執行都是n=1000啊,似乎volatile有用,這還是原子操作哈
    2009-03-19 19:21 | qiulijian

    # re: Java多線程初學者指南(6):慎重使用volatile關鍵字  回復  更多評論   

    @qiulijian
    你多運行幾次,如運行20次再說,第一個例子不同步,第二個例子是同步的
    2009-03-19 19:29 | 銀河使者

    # re: Java多線程初學者指南(6):慎重使用volatile關鍵字  回復  更多評論   

    這里有自動拆封箱操作,n的對象一直在變化。
    2015-08-26 16:40 | 皮鞋錚亮
    主站蜘蛛池模板: 亚洲另类激情综合偷自拍图| 免费人成在线观看播放国产 | 日韩毛片免费在线观看| 亚洲另类古典武侠| 久久久久久曰本AV免费免费| 久久精品国产精品亚洲色婷婷| 中文字幕在线免费播放| 在线观看亚洲精品国产| 美女无遮挡拍拍拍免费视频| 亚洲一级特黄无码片| 久久九九久精品国产免费直播| 亚洲国产精品一区二区第四页| 日本永久免费a∨在线视频| 亚洲日本在线观看视频| 久久国产精品免费一区二区三区| 国产亚洲精品拍拍拍拍拍| 国产特黄特色的大片观看免费视频 | 国产桃色在线成免费视频| 亚洲国产成人综合| 国产免费av片在线看| 亚洲.国产.欧美一区二区三区| 国产成人免费a在线视频app| 风间由美在线亚洲一区| 亚洲高清免费视频| AAA日本高清在线播放免费观看| 亚洲国产高清视频| 最近最新中文字幕完整版免费高清| 亚洲精品中文字幕| 国产L精品国产亚洲区久久| 日韩免费电影网站| 午夜在线a亚洲v天堂网2019| 国产zzjjzzjj视频全免费 | 亚洲精品黄色视频在线观看免费资源| 男女啪啪免费体验区| 亚洲av无码av制服另类专区| 国产成人精品免费视频网页大全 | 久久久久久毛片免费看 | 亚洲国产夜色在线观看| 无码不卡亚洲成?人片| 久久久久成人片免费观看蜜芽| 亚洲专区一路线二|