<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## Java編程那些事兒98——多線程問題及處理1 陳躍峰 出自:[http://blog.csdn.net/mailbomb](http://blog.csdn.net/mailbomb) ### 12.4 多線程問題及處理 多線程編程為程序開發帶來了很多的方便,但是也帶來了一些問題,這些問題是在程序開發過程中必須進行處理的問題。 這些問題的核心是,如果多個線程同時訪問一個資源,例如變量、文件等,時如何保證訪問安全的問題。在多線程編程中,這種會被多個線程同時訪問的資源叫做臨界資源。 下面通過一個簡單的示例,演示多個線程訪問臨界資源時產生的問題。在該示例中,啟動了兩個線程類DataThread的對象,該線程每隔200毫秒輸出一次變量n的值,并將n的值減少1。變量n的值存儲在模擬臨界資源的Data類中,該示例的核心是兩個線程類都使用同一個Data類的對象,這樣Data類的這個對象就是一個臨界資源了。示例代碼如下: package syn1; ~~~ /** ?* 模擬臨界資源的類 ?*/ public class Data { ???????? public int n; ???????? public Data(){ ?????????????????? n = 60; ???????? } } package syn1; /** ?* 測試多線程訪問時的問題 ?*/ public class TestMulThread1 { ???????? public static void main(String[] args) { ?????????????????? Data data = new Data(); ?????????????????? DataThread d1 = new DataThread(data,"線程1"); ?????????????????? DataThread d2 = new DataThread(data,"線程2"); ???????? } } package syn1; /** ?* 訪問數據的線程 ?*/ public class DataThread extends Thread { ???????? Data data; ???????? String name; ???????? public DataThread(Data data,String name){ ?????????????????? this.data = data; ?????????????????? this.name = name; ?????????????????? start(); ???????? } ???????? ? ???????? public void run(){ ?????????????????? try{ ??????????????????????????? for(int i = 0;i < 10;i++){ ???????????????????????????????????? System.out.println(name + ":" + data.n); ???????????????????????????????????? data.n--; ???????????????????????????????????? Thread.sleep(200); ??????????????????????????? } ?????????????????? }catch(Exception e){} ???????? } } ~~~ 在運行時,因為不同情況下該程序的運行結果會出現不同,該程序的一種執行結果為: 線程1:60 線程2:60 線程2:58 線程1:58 線程2:56 線程1:56 線程2:54 線程1:54 線程2:52 線程1:52 線程2:50 線程1:50 線程2:48 線程1:48 線程2:47 線程1:46 線程2:44 線程1:44 線程2:42 線程1:42 從執行結果來看,第一次都輸出60是可以理解的,因為線程在執行時首先輸出變量的值,這個時候變量n的值還是初始值60,而后續的輸出就比較麻煩了,在開始的時候兩個變量保持一致的輸出,而不是依次輸出n的每個值的內容,而到將要結束時,線程2輸出47這個中間數值。 出現這種結果的原因很簡單:線程1改變了變量n的值以后,還沒有來得及輸出,這個變量n的值就被線程2給改變了,所以在輸出時看的輸出都是跳躍的,偶爾出現了連續。 出現這個問題也比較容易接受,因為最基本的多線程程序,系統只保證線程同時執行,至于哪個先執行,哪個后執行,或者執行中會出現一個線程執行到一半,就把CPU的執行權交給了另外一個線程,這樣線程的執行順序是隨機的,不受控制的。所以會出現上面的結果。 這種結果在很多實際應用中是不能被接受的,例如銀行的應用,兩個人同時取一個賬戶的存款,一個使用存折、一個使用卡,這樣訪問賬戶的金額就會出現問題。或者是售票系統中,如果也這樣就出現有人買到相同座位的票,而有些座位的票卻未售出。 在多線程編程中,這個是一個典型的臨界資源問題,解決這個問題最基本,最簡單的思路就是使用同步關鍵字synchronized。 synchronized關鍵字是一個修飾符,可以修飾方法或代碼塊,其的作用就是,對于同一個對象(不是一個類的不同對象),當多個線程都同時調用該方法或代碼塊時,必須依次執行,也就是說,如果兩個或兩個以上的線程同時執行該段代碼時,如果一個線程已經開始執行該段代碼,則另外一個線程必須等待這個線程執行完這段代碼才能開始執行。就和在銀行的柜臺辦理業務一樣,營業員就是這個對象,每個顧客就好比線程,當一個顧客開始辦理時,其它顧客都必須等待,及時這個正在辦理的顧客在辦理過程中接了一個電話 (類比于這個線程釋放了占用CPU的時間,而處于阻塞狀態),其它線程也只能等待。 使用synchronized關鍵字修改以后的上面的代碼為: package syn2; ~~~ /** ?* 模擬臨界資源的類 ?*/ public class Data2 { ???????? public int n; ???????? public Data2(){ ?????????????????? n = 60; ???????? } ???????? ???????? public synchronized void action(String name){ ?????????????????? System.out.println(name + ":" + n); ?????????????????? n--; ???????? } } package syn2; /** ?* 測試多線程訪問時的問題 ?*/ public class TestMulThread2 { ???????? public static void main(String[] args) { ?????????????????? Data2 data = new Data2(); ?????????????????? Data2Thread d1 = new Data2Thread(data,"線程1"); ?????????????????? Data2Thread d2 = new Data2Thread(data,"線程2"); ???????? } } package syn2; /** ?* 訪問數據的線程 ?*/ public class Data2Thread extends Thread { ???????? Data2 data; ???????? String name; ???????? public Data2Thread(Data2 data,String name){ ?????????????????? this.data = data; ?????????????????? this.name = name; ?????????????????? start(); ???????? } ???????? ? ???????? public void run(){ ?????????????????? try{ ??????????????????????????? for(int i = 0;i < 10;i++){ ???????????????????????????????????? data.action(name); ???????????????????????????????????? Thread.sleep(200); ??????????????????????????? } ?????????????????? }catch(Exception e){} ???????? } } ~~~ 該示例代碼的執行結果會出現不同,一種執行結果為: 線程1:60 線程2:59 線程2:58 線程1:57 線程2:56 線程1:55 線程2:54 線程1:53 線程2:52 線程1:51 線程2:50 線程1:49 線程1:48 線程2:47 線程2:46 線程1:45 線程2:44 線程1:43 線程2:42 線程1:41 在該示例中,將打印變量n的代碼和變量n變化的代碼組成一個專門的方法action,并且使用修飾符synchronized修改該方法,也就是說對于一個Data2的對象,無論多少個線程同時調用action方法時,只有一個線程完全執行完該方法以后,別的線程才能夠執行該方法。這就相當于一個線程執行到該對象的synchronized方法時,就為這個對象加上了一把鎖,鎖住了這個對象,別的線程在調用該方法時,發現了這把鎖以后就繼續等待下去了。 ?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看