posts - 4,  comments - 9,  trackbacks - 0

           線程安全的本質體現在兩個方面,

            A變量安全:多線程同時運行一段代碼

            B線程同步:一個線程還沒執行完,另一個線程又進來接著執行。

           看個簡單的例子。

          Java代碼
          1. public class ThreadSafe implements java.lang.Runnable {  
          2.       
          3.     int num = 1;  
          4.     public void run() {  
          5.         for (int i = 0; i < 3; i++) {  
          6.             num = num + 1;  
          7.             try {  
          8.                 Thread.sleep(2000);  
          9.             } catch (InterruptedException e) {  
          10.                 e.printStackTrace();  
          11.             }  
          12.             System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + num);  
          13.         }  
          14.     }  
          15.   
          16. }  
           
          TestMan.java 寫道
          package com.java.thread.test;

          public class TestMan {
          public static void main(String[] args) {
          Runnable safe=new ThreadSafe();
          Thread thread1=new Thread(safe,"thread1");
          Thread thread2=new Thread(safe,"thread2");
          thread1.start();
          thread2.start();
          }

          }

           運行結果

          num is value +===thread2---------3
          num is value +===thread1---------4
          num is value +===thread2---------5
          num is value +===thread1---------6
          num is value +===thread1---------7
          num is value +===thread2---------7

          很明顯是錯誤的,應為兩個線程共享同一個變量。這里就是變量的安全問題。

          解決辦法:

          1拋棄單實例,多線程的方式,用多實例,多線程的方式,這樣就和單線程是一個樣了,不會出錯,但是是最接近傳統的編程模式

          2不要用類的實例變量,經可能把變量封裝到方法內部。

          1類的解決辦法的代碼。

          Java代碼
          1. public class TestMan {  
          2.     public static void main(String[] args) {  
          3.         Runnable safe=new ThreadSafe();  
          4.         Runnable safe2=new ThreadSafe();  
          5.         Thread thread1=new Thread(safe,"thread1");  
          6.         Thread thread2=new Thread(safe2,"thread2");  
          7.         thread1.start();  
          8.         thread2.start();  
          9.     }  
          10.   
          11. }  
           

          運行結果

          num is value +===thread1---------2
          num is value +===thread2---------2
          num is value +===thread1---------3
          num is value +===thread2---------3
          num is value +===thread1---------4
          num is value +===thread2---------4
          2類解決辦法的代碼

          Java代碼
          1. public class ThreadSafe implements java.lang.Runnable {  
          2.       
          3.     public void run() {  
          4.         int num = 1;  
          5.         for (int i = 0; i < 3; i++) {  
          6.             num = num + 1;  
          7.             try {  
          8.                 Thread.sleep(2000);  
          9.             } catch (InterruptedException e) {  
          10.                 e.printStackTrace();  
          11.             }  
          12.             System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + num);  
          13.         }  
          14.     }  
          15.   
          16. }  
           
          Java代碼
          1. public class TestMan {  
          2.     public static void main(String[] args) {  
          3.         Runnable safe=new ThreadSafe();  
          4.   
          5.         Thread thread1=new Thread(safe,"thread1");  
          6.         Thread thread2=new Thread(safe,"thread2");  
          7.         thread1.start();  
          8.         thread2.start();  
          9.     }  
          10.   
          11. }  

           運行結果

          num is value +===thread2---------2
          num is value +===thread1---------2
          num is value +===thread1---------3
          num is value +===thread2---------3
          num is value +===thread1---------4
          num is value +===thread2---------4

           

          這兩種辦法,比較推薦適用第二個辦法,就是把變量經可能的封裝到風發內部,這樣他們就是線程的私有變量了。另外,從jdk1.2后,推出了 threadlocal 對象,它作為線程的一個局部變量,可以為每個線程創建一個副本,用來保存每個線程的屬性,各是各的,互不干擾。單每個 threadlocal變量只能保存一個變量,假如有多個變量要保存,那么就要寫多個threadlocal對象。

           

          我們把代碼改寫一下。

          Java代碼
          1. public class ThreadSafe implements java.lang.Runnable {  
          2.     ThreadLocal<Integer> local=new ThreadLocal<Integer>();  
          3.     public void run() {  
          4.         for (int i = 0; i < 3; i++) {  
          5.             if(local.get()==null){  
          6.                 local.set(new Integer(1));  
          7.             }  
          8.             int num=local.get().intValue();  
          9.             num=num+1;  
          10.             local.set(new Integer(num));  
          11.             try {  
          12.                 Thread.sleep(2000);  
          13.             } catch (InterruptedException e) {  
          14.                 e.printStackTrace();  
          15.             }  
          16.             System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + local.get().intValue());  
          17.         }  
          18.     }  
          19.   
          20. }  
           
          Java代碼
          1. public class TestMan {  
          2.     public static void main(String[] args) {  
          3.         Runnable safe=new ThreadSafe();  
          4.         Thread thread1=new Thread(safe,"thread1");  
          5.         Thread thread2=new Thread(safe,"thread2");  
          6.         thread1.start();  
          7.         thread2.start();  
          8.     }  
          9.   
          10. }  

           運行結果

          num is value +===thread2---------2
          num is value +===thread1---------2
          num is value +===thread1---------3
          num is value +===thread2---------3
          num is value +===thread1---------4
          num is value +===thread2---------4

          結果是一樣的,所以這里變量安全有3個辦法可以解決。

           

          然后在說說線程的同步的問題。我們看上面的運行結果。

          num is value +===thread2---------2
          num is value +===thread1---------2
          num is value +===thread1---------3
          num is value +===thread2---------3
          num is value +===thread1---------4
          num is value +===thread2---------4

          就 可以看出他們不是線程同步的,是thread1和thread2在交替執行的。在有些情況下,要求一段代碼在運行的過程中是一個不可分割的實 體,就是原子的。就是說當已經有線程在執行這段代碼的時候,其他的線程必須等待他執行完畢后才能竟來執行,這就是所謂的線程同步。

           

          java通過同步鎖來執行線程的同步和等待,也就是說,要不間斷執行的代碼需要放在synchronized關鍵字標識的代碼塊中。可以用來修飾代 碼塊,也可以修飾方法。

           

          Java代碼
          1. public class ThreadSafe implements java.lang.Runnable{  
          2.     public synchronized void run() {  
          3.         int num = 1;  
          4.         for (int i = 0; i < 3; i++) {  
          5.             num = num + 1;  
          6.             try {  
          7.                 Thread.sleep(2000);  
          8.             } catch (InterruptedException e) {  
          9.                 e.printStackTrace();  
          10.             }  
          11.             System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + num);  
          12.         }  
          13.     }  
          14.   
          15.   
          16. }  
           
          Java代碼
          1. public class TestMan {  
          2.     public static void main(String[] args) {  
          3.         Runnable safe=new ThreadSafe();  
          4.         Thread thread1=new Thread(safe,"thread1");  
          5.         Thread thread2=new Thread(safe,"thread2");  
          6.         thread1.start();  
          7.         thread2.start();  
          8.     }  
          9.   
          10. }  

           運行結果

          um is value +===thread1---------2
          num is value +===thread1---------3
          num is value +===thread1---------4
          num is value +===thread2---------2
          num is value +===thread2---------3
          num is value +===thread2---------4

           

          可以看到thread1運行結束后thread2才開始運行的。代碼還可以這么寫

          Java代碼
          1. public class ThreadSafe implements java.lang.Runnable {  
          2.     public void run() {  
          3.         int num = 1;  
          4.         synchronized (this) {  
          5.             for (int i = 0; i < 3; i++) {  
          6.                 num = num + 1;  
          7.                 try {  
          8.                     Thread.sleep(2000);  
          9.                 } catch (InterruptedException e) {  
          10.                     e.printStackTrace();  
          11.                 }  
          12.                 System.out.println("num is value +==="  
          13.                         + Thread.currentThread().getName() + "---------" + num);  
          14.             }  
          15.         }  
          16.     }  
          17.   
          18. }  
           

          在啟用同步鎖機制以后,需要避免

          1無線等待,,線程B等待線程A執行完畢,然后線程A確進入了死循環。

          2循環等待:兩個線程相互調用,都要求要同步執行,這個時候就先會循環等待,我等你執行,你也在等我執行,這個時候就死鎖了
          posted on 2010-06-05 17:23 凌宇 閱讀(3613) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(3)

          隨筆檔案(3)

          文章檔案(14)

          相冊

          收藏夾

          Java

          最新隨筆

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 遵化市| 九江县| 英山县| 庆元县| 天镇县| 嘉峪关市| 金昌市| 崇明县| 凌云县| 台湾省| 陇西县| 苏尼特左旗| 澜沧| 化德县| 舞阳县| 郑州市| 青州市| 霞浦县| 安平县| 峨山| 炎陵县| 监利县| 广饶县| 东山县| 华池县| 鹰潭市| 呼图壁县| 嘉黎县| 锡林郭勒盟| 长治县| 武宁县| 三穗县| 女性| 宜春市| 象州县| 江孜县| 中西区| 台南市| 台安县| 新余市| 张家港市|