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

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

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

    posts - 4,  comments - 9,  trackbacks - 0

     線程安全的本質(zhì)體現(xiàn)在兩個(gè)方面,

      A變量安全:多線程同時(shí)運(yùn)行一段代碼

      B線程同步:一個(gè)線程還沒(méi)執(zhí)行完,另一個(gè)線程又進(jìn)來(lái)接著執(zhí)行。

     看個(gè)簡(jiǎn)單的例子。

    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 寫(xiě)道
    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();
    }

    }

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

    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

    很明顯是錯(cuò)誤的,應(yīng)為兩個(gè)線程共享同一個(gè)變量。這里就是變量的安全問(wèn)題。

    解決辦法:

    1拋棄單實(shí)例,多線程的方式,用多實(shí)例,多線程的方式,這樣就和單線程是一個(gè)樣了,不會(huì)出錯(cuò),但是是最接近傳統(tǒng)的編程模式

    2不要用類的實(shí)例變量,經(jīng)可能把變量封裝到方法內(nèi)部。

    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. }  
     

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

    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. }  

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

    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

     

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

     

    我們把代碼改寫(xiě)一下。

    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. }  

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

    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

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

     

    然后在說(shuō)說(shuō)線程的同步的問(wèn)題。我們看上面的運(yùn)行結(jié)果。

    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在交替執(zhí)行的。在有些情況下,要求一段代碼在運(yùn)行的過(guò)程中是一個(gè)不可分割的實(shí) 體,就是原子的。就是說(shuō)當(dāng)已經(jīng)有線程在執(zhí)行這段代碼的時(shí)候,其他的線程必須等待他執(zhí)行完畢后才能竟來(lái)執(zhí)行,這就是所謂的線程同步。

     

    java通過(guò)同步鎖來(lái)執(zhí)行線程的同步和等待,也就是說(shuō),要不間斷執(zhí)行的代碼需要放在synchronized關(guān)鍵字標(biāo)識(shí)的代碼塊中。可以用來(lái)修飾代 碼塊,也可以修飾方法。

     

    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. }  

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

    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運(yùn)行結(jié)束后thread2才開(kāi)始運(yùn)行的。代碼還可以這么寫(xiě)

    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. }  
     

    在啟用同步鎖機(jī)制以后,需要避免

    1無(wú)線等待,,線程B等待線程A執(zhí)行完畢,然后線程A確進(jìn)入了死循環(huán)。

    2循環(huán)等待:兩個(gè)線程相互調(diào)用,都要求要同步執(zhí)行,這個(gè)時(shí)候就先會(huì)循環(huán)等待,我等你執(zhí)行,你也在等我執(zhí)行,這個(gè)時(shí)候就死鎖了
    posted on 2010-06-05 17:23 凌宇 閱讀(3609) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(3)

    隨筆檔案(3)

    文章檔案(14)

    相冊(cè)

    收藏夾

    Java

    最新隨筆

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 成人免费ā片在线观看| 亚洲国产精品13p| 免费人成激情视频在线观看冫| 精品丝袜国产自在线拍亚洲| 国产精品久久久亚洲| 国产一区二区三区在线免费观看| 永久免费在线观看视频| 中文在线免费观看| 免费国产在线精品一区| 中文字幕亚洲情99在线| 亚洲精品国产成人中文| 亚洲AV无码AV男人的天堂| 国产偷国产偷亚洲高清日韩| 国产裸模视频免费区无码| 99久久免费精品国产72精品九九| 91香焦国产线观看看免费| CAOPORN国产精品免费视频| 黄色毛片免费网站| 亚洲高清毛片一区二区| 亚洲国产成人精品激情| 亚洲美免无码中文字幕在线| 久久亚洲国产中v天仙www| 亚洲人成影院在线无码观看| 亚洲国产高清精品线久久| 免费一级成人毛片| 国产在线观看免费视频播放器| 在线免费视频一区| 毛片高清视频在线看免费观看| 嫖丰满老熟妇AAAA片免费看| xxxxwww免费| 日本一区二区三区免费高清| 99久久国产热无码精品免费 | 在线观看视频免费完整版| 免费女人高潮流视频在线观看| 免费国产叼嘿视频大全网站| 国内少妇偷人精品视频免费| 久久精品私人影院免费看| 99视频有精品视频免费观看| 0588影视手机免费看片| 成年女人男人免费视频播放| 免费无码不卡视频在线观看|