乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      java線程安全問題之靜態(tài)變量、實(shí)例變量、局部變量

       WaterStoneShi 2016-06-22

       java多線程編程中,存在很多線程安全問題,至于什么是線程安全呢,給出一個(gè)通俗易懂的概念還是蠻難的,如同《java并發(fā)編程實(shí)踐》中所說:

      寫道
      給線程安全下定義比較困難。存在很多種定義,如:“一個(gè)類在可以被多個(gè)線程安全調(diào)用時(shí)就是線程安全的”。 

       此處不贅述了,首先給出靜態(tài)變量、實(shí)例變量、局部變量在多線程環(huán)境下的線程安全問題結(jié)論,然后用示例驗(yàn)證,請大家擦亮眼睛,有錯(cuò)必究,否則誤人子弟!

       

      靜態(tài)變量:線程非安全。

      靜態(tài)變量即類變量,位于方法區(qū),為所有對象共享,共享一份內(nèi)存,一旦靜態(tài)變量被修改,其他對象均對修改可見,故線程非安全。

      實(shí)例變量:單例模式(只有一個(gè)對象實(shí)例存在)線程非安全,非單例線程安全。

      實(shí)例變量為對象實(shí)例私有,在虛擬機(jī)的堆中分配,若在系統(tǒng)中只存在一個(gè)此對象的實(shí)例,在多線程環(huán)境下,“猶如”靜態(tài)變量那樣,被某個(gè)線程修改后,其他線程對修改均可見,故線程非安全;如果每個(gè)線程執(zhí)行都是在不同的對象中,那對象與對象之間的實(shí)例變量的修改將互不影響,故線程安全。

      局部變量:線程安全。

      每個(gè)線程執(zhí)行時(shí)將會把局部變量放在各自棧幀的工作內(nèi)存中,線程間不共享,故不存在線程安全問題。

       

      靜態(tài)變量線程安全問題模擬:

      ----------------------------------------------------------------------------------

      Java代碼  收藏代碼
      1. /**  
      2.   * 線程安全問題模擬執(zhí)行  
      3.   *  ------------------------------  
      4.   *       線程1      |    線程2  
      5.   *  ------------------------------  
      6.   *   static_i = 4;  | 等待  
      7.   *   static_i = 10; | 等待  
      8.   *    等待          | static_i = 4;  
      9.   *   static_i * 2;  | 等待  
      10.   *  ----------------------------- 
      11.  * */  
      12. public class Test implements Runnable  
      13. {  
      14.     private static int static_i;//靜態(tài)變量   
      15.       
      16.     public void run()  
      17.     {  
      18.         static_i = 4;  
      19.         System.out.println('[' + Thread.currentThread().getName()  
      20.                 + ']獲取static_i 的值:' + static_i);  
      21.         static_i = 10;  
      22.         System.out.println('[' + Thread.currentThread().getName()  
      23.                 + ']獲取static_i*3的值:' + static_i * 2);  
      24.     }  
      25.       
      26.     public static void main(String[] args)  
      27.     {  
      28.         Test t = new Test();  
      29.         //啟動盡量多的線程才能很容易的模擬問題   
      30.         for (int i = 0; i <>3000; i++)  
      31.         {  
      32.             //t可以換成new Test(),保證每個(gè)線程都在不同的對象中執(zhí)行,結(jié)果一樣   
      33.             new Thread(t, '線程' + i).start();  
      34.         }  
      35.     }  
      36. }  

       

       

      根據(jù)代碼注釋中模擬的情況,當(dāng)線程1執(zhí)行了static_i = 4;  static_i = 10; 后,線程2獲得執(zhí)行權(quán),static_i = 4; 然后當(dāng)線程1獲得執(zhí)行權(quán)執(zhí)行static_i * 2;  必然輸出結(jié)果4*2=8,按照這個(gè)模擬,我們可能會在控制臺看到輸出為8的結(jié)果。

      寫道
      [線程27]獲取static_i 的值:4 
      [線程22]獲取static_i*2的值:20 
      [線程28]獲取static_i 的值:4 
      [線程23]獲取static_i*2的值:8 
      [線程29]獲取static_i 的值:4 
      [線程30]獲取static_i 的值:4 
      [線程31]獲取static_i 的值:4 
      [線程24]獲取static_i*2的值:20

       看紅色標(biāo)注的部分,確實(shí)出現(xiàn)了我們的預(yù)想,同樣也證明了我們的結(jié)論。

       

      實(shí)例變量線程安全問題模擬:

      ----------------------------------------------------------------------------------

      Java代碼  收藏代碼
      1. public class Test implements Runnable  
      2. {  
      3.     private int instance_i;//實(shí)例變量  
      4.       
      5.     public void run()  
      6.     {  
      7.         instance_i = 4;  
      8.         System.out.println('[' + Thread.currentThread().getName()  
      9.                 + ']獲取instance_i 的值:' + instance_i);  
      10.         instance_i = 10;  
      11.         System.out.println('[' + Thread.currentThread().getName()  
      12.                 + ']獲取instance_i*3的值:' + instance_i * 2);  
      13.     }  
      14.       
      15.     public static void main(String[] args)  
      16.     {  
      17.         Test t = new Test();  
      18.         //啟動盡量多的線程才能很容易的模擬問題   
      19.         for (int i = 0; i <>3000; i++)  
      20.         {  
      21.             //每個(gè)線程對在對象t中運(yùn)行,模擬單例情況  
      22.             new Thread(t, '線程' + i).start();  
      23.         }  
      24.     }  
      25. }  

       

       

      按照本文開頭的分析,猶如靜態(tài)變量那樣,每個(gè)線程都在修改同一個(gè)對象的實(shí)例變量,肯定會出現(xiàn)線程安全問題。

      寫道

      [線程66]獲取instance_i 的值:10 
      [線程33]獲取instance_i*2的值:20 
      [線程67]獲取instance_i 的值:4 
      [線程34]獲取instance_i*2的值:8 
      [線程35]獲取instance_i*2的值:20 
      [線程68]獲取instance_i 的值:4

       

      看紅色字體,可知單例情況下,實(shí)例變量線程非安全。

       

      將new Thread(t, '線程' + i).start();改成new Thread(new Test(), '線程' + i).start();模擬非單例情況,會發(fā)現(xiàn)不存在線程安全問題。

       

       

      局部變量線程安全問題模擬:

      ----------------------------------------------------------------------------------

       

      Java代碼  收藏代碼
      1. public class Test implements Runnable  
      2. {  
      3.     public void run()  
      4.     {  
      5.         int local_i = 4;  
      6.         System.out.println('[' + Thread.currentThread().getName()  
      7.                 + ']獲取local_i 的值:' + local_i);  
      8.         local_i = 10;  
      9.         System.out.println('[' + Thread.currentThread().getName()  
      10.                 + ']獲取local_i*2的值:' + local_i * 2);  
      11.     }  
      12.       
      13.     public static void main(String[] args)  
      14.     {  
      15.         Test t = new Test();  
      16.         //啟動盡量多的線程才能很容易的模擬問題  
      17.         for (int i = 0; i <>3000; i++)  
      18.         {  
      19.             //每個(gè)線程對在對象t中運(yùn)行,模擬單例情況   
      20.             new Thread(t, '線程' + i).start();  
      21.         }  
      22.     }  
      23. }  

       

       

      控制臺沒有出現(xiàn)異常數(shù)據(jù)。

       

      ---------------------------------------------------------------

      以上只是通過簡單的實(shí)例來展示靜態(tài)變量、實(shí)例變量、局部變量等的線程安全問題,

      并未進(jìn)行底層的分析,下一篇將對線程問題的底層進(jìn)行剖析。


      靜態(tài)方法是線程安全的

      先看一個(gè)類

      public class  Test{

      public static  String hello(String str){

          String tmp='';

          tmp  =  tmp+str;

         return tmp;

      }

      }

      hello方法會不會有多線程安全問題呢?沒有??!

      靜態(tài)方法如果沒有使用靜態(tài)變量,則沒有線程安全問題。

      為什么呢?因?yàn)殪o態(tài)方法內(nèi)聲明的變量,每個(gè)線程調(diào)用時(shí),都會新創(chuàng)建一份,而不會共用一個(gè)存儲單元。比如這里的tmp,每個(gè)線程都會創(chuàng)建自己的一份,因此不會有線程安全問題

       

      注意,靜態(tài)變量,由于是在類加載時(shí)占用一個(gè)存儲區(qū),每個(gè)線程都是共用這個(gè)存儲區(qū)的,所以如果在靜態(tài)方法里使用了靜態(tài)變量,這就會有線程安全問題!

      總結(jié):只要方法內(nèi)含有靜態(tài)變量,就是非線程安全的

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多