<strike id="kouok"></strike>
  • <abbr id="kouok"></abbr>
    <ul id="kouok"></ul>
    • <ul id="kouok"></ul>

      南京軟件定制開發

      南京傾心軟件歡迎您訪問本站

      13605185909

      新聞資訊

      NEWS CENTER
      欄目導航

      南京軟件開發之AutoResetEvent使用介紹

      發布時間:Mar 23, 2021         已有 人瀏覽

      之前在博客園看到有位仁兄發表一篇關于AutoResetEvent介紹,看了下他寫的代碼,看上去沒什么問題,但仔細看還是能發現問題。下圖是這位仁兄代碼截圖。

      仁兄博客地址:http://www.cnblogs.com/lzjsky/archive/2011/07/11/2102794.html

      按照這種寫法自己試了下,運行起來并不是他這種結果(運行結果很隨機)。

      原因有以下兩點:

      1、支付線程與取書線程都屬于同級線程,運行先后順序是隨機的

      2、在循環內部調用AutoResetEvent.Set(),不能確定子線程是否按順序執行,有可能主線程已經循環多次,而子線程可能才循環一次

      修正

      首先,要明白實驗的場景。還是引用這位仁兄的例子:“我去書店買書,當我選中一本書后我會去收費處付錢,付好錢后再去倉庫取書。這個順序不能顛倒,我作為主線程,收費處和倉庫做兩個輔助線程” 。

      要實現上圖這種效果,得先確定好執行先后順序(上面已經說過):挑書-->收費-->取書-->完成

      代碼編寫如下:

      復制代碼
       1 class Program
       2     {
       3         static int _num = 0;
       4         //本例重點對象
       5         static AutoResetEvent _autoReset = new AutoResetEvent(false);
       6 
       7         static AutoResetEvent _autoReset0 = new AutoResetEvent(false);
       8         static AutoResetEvent _autoReset1 = new AutoResetEvent(false);
       9 
      10         //static AutoResetEvent autoReset2 = new AutoResetEvent(false);
      11         //static AutoResetEvent autoReset3 = new AutoResetEvent(false);
      12 
      13         //static object _payMoneyObj = new object();
      14         //static object _getBookObj = new object();
      15 
      16         private static void ThreadPayMoneyProc()
      17         {
      18             while (true)
      19             {
      20                 //_autoReset.WaitOne();
      21                 _autoReset0.WaitOne();
      22                 //lock (_payMoneyObj)
      23                 {
      24                     Console.WriteLine(Thread.CurrentThread.Name + ",編號: " + _num);
      25                     //通知主線程,錢已付完
      26                     //_autoReset2.Set();
      27                 }
      28             }
      29         }
      30 
      31         private static void TreadGetBookProc()
      32         {
      33             while (true)
      34             {
      35                 //_autoReset.WaitOne();
      36                 _autoReset1.WaitOne();
      37                 //lock (_getBookObj)
      38                 {
      39                     Console.WriteLine(Thread.CurrentThread.Name + ",編號: " + _num);
      40                     //通知主線程,書已取走
      41                     //_autoReset3.Set();
      42                 }
      43             }
      44         }
      45 
      46 
      47         static void Main(string[] args)
      48         {
      49             //本案例是通過AutoResetEvent來實現多線程同步
      50             //購買書數量
      51             const int num = 50;
      52 
      53             //付錢線程
      54             Thread threadPayMoney = new Thread(new ThreadStart(ThreadPayMoneyProc));
      55             threadPayMoney.Name = "付錢線程";
      56             //取書線程
      57             Thread threadGetBook = new Thread(new ThreadStart(TreadGetBookProc));
      58             threadGetBook.Name = "取書線程";
      59 
      60             //開始執行線程
      61             threadPayMoney.Start();
      62             threadGetBook.Start();
      63 
      64             //主線程開始選書
      65             Console.WriteLine("----------------主線程開始選書!------------------");
      66             for (int i = 1; i <= num; i++)
      67             {
      68                 Console.WriteLine("主線程選書編號:" + i);
      69                 _num = i;
      70                 //_autoReset.Set();
      71 
      72                 //通知付錢線程
      73                 _autoReset0.Set();
      74                 //主線延時1ms執行(但不知道付錢線程這個過程需要多少時間)
      75                 Thread.Sleep(1);
      76                 //_autoReset2.WaitOne();
      77 
      78                 //付完錢后,通知取書線程
      79                 _autoReset1.Set();
      80                 //主線延時1ms執行(但不知道取書線程這個過程需要多少時間)
      81                 Thread.Sleep(1);
      82                 //_autoReset3.WaitOne();
      83                 Console.WriteLine("-----------------------------------");
      84             }
      85 
      86             Console.ReadKey();
      87 
      88 
      89         }
      90     }
      復制代碼

      運行結果如下圖:

      這樣做,效果是出來了,但主線程不知道付費線程、取書線程執行需要多長時間。上例中給定的是1ms,但如果其中某個子線程超過了給定的休眠時間,主線會繼續往下執行,不會等待子線程處理完成。這樣就導致了買書編號與付錢和取書的編號不同步。也就混亂了。

      這時可以使用AutoResetEvent這個對象。上例中已經使用這個對象。沒錯,還可以在繼續使用。

      代碼如下圖:

      復制代碼
       1 class Program
       2     {
       3         static int _num = 0;
       4         //本例重點對象
       5         static AutoResetEvent _autoReset = new AutoResetEvent(false);
       6 
       7         static AutoResetEvent _autoReset0 = new AutoResetEvent(false);
       8         static AutoResetEvent _autoReset1 = new AutoResetEvent(false);
       9 
      10         static AutoResetEvent _autoReset2 = new AutoResetEvent(false);
      11         static AutoResetEvent _autoReset3 = new AutoResetEvent(false);
      12 
      13         //static object _payMoneyObj = new object();
      14         //static object _getBookObj = new object();
      15 
      16         private static void ThreadPayMoneyProc()
      17         {
      18             while (true)
      19             {
      20                 //_autoReset.WaitOne();
      21                 _autoReset0.WaitOne();
      22                 //lock (_payMoneyObj)
      23                 {
      24                     Console.WriteLine(Thread.CurrentThread.Name + ",編號: " + _num);
      25                     //通知主線程,錢已付完成
      26                     _autoReset2.Set();
      27                 }
      28             }
      29         }
      30 
      31         private static void TreadGetBookProc()
      32         {
      33             while (true)
      34             {
      35                 //_autoReset.WaitOne();
      36                 _autoReset1.WaitOne();
      37                 //lock (_getBookObj)
      38                 {
      39                     Console.WriteLine(Thread.CurrentThread.Name + ",編號: " + _num);
      40                     //通知主線程,書已取走
      41                     _autoReset3.Set();
      42                 }
      43             }
      44         }
      45 
      46 
      47         static void Main(string[] args)
      48         {
      49             //本案例是通過AutoResetEvent來實現多線程同步
      50             //購買書數量
      51             const int num = 5;
      52 
      53             //付錢線程
      54             Thread threadPayMoney = new Thread(new ThreadStart(ThreadPayMoneyProc));
      55             threadPayMoney.Name = "付錢線程";
      56             //取書線程
      57             Thread threadGetBook = new Thread(new ThreadStart(TreadGetBookProc));
      58             threadGetBook.Name = "取書線程";
      59 
      60             //開始執行線程
      61             threadPayMoney.Start();
      62             threadGetBook.Start();
      63 
      64             //主線程開始選書
      65             Console.WriteLine("----------------主線程開始選書!------------------");
      66             for (int i = 1; i <= num; i++)
      67             {
      68                 Console.WriteLine("主線程選書編號:" + i);
      69                 _num = i;
      70                 //_autoReset.Set();
      71 
      72                 //通知付錢線程
      73                 _autoReset0.Set();
      74                 //主線延時1ms執行(但不知道付錢線程這個過程需要多少時間)
      75                 //Thread.Sleep(1);
      76                 //等待付錢線程
      77                 _autoReset2.WaitOne();
      78 
      79                 //付完錢后,通知取書線程
      80                 _autoReset1.Set();
      81                 //主線延時1ms執行(但不知道取書線程這個過程需要多少時間)
      82                 //Thread.Sleep(1);
      83                 //等待取書線程
      84                 _autoReset3.WaitOne();
      85                 Console.WriteLine("-----------------------------------");
      86                 //完成后,繼續下一個任務處理
      87             }
      88 
      89             Console.ReadKey();
      90 
      91 
      92         }
      93     }
      復制代碼

      運行結果如下圖:

      運行結果和上面使用指定主線程休眠所運行結果是一樣的。但是,可以不用指定主線程休眠時間,也不需要指定。因為你沒法估計子線程所運行的時間,而且每次運行時間都不一樣。

      后話

      本例中, 買書場景其實有兩種編程結構(或者編程思想)。一種是本例中的,買書是主線程,而收銀臺(付錢線程)、倉庫(取書線程)。這兩個線程是一直存在的,一直跑著的。只要有書過來,這兩個線程就會執行。這可以聯系到現實中的收銀臺和倉庫。

      第二種編程思想,買書是一個發起線程,然后開啟一個付款線程和取書線程。這時,買書線程(主線程)可以確定這兩個子線程什么時候執行完成。使用 線程對象.Join(),執行完后,主線程接著下步任務處理。

      Copyright © 2020-2022 南京傾心軟件技術有限公司 版權所有     蘇ICP備2020070309號-1
      QQ在線咨詢
      13605185909
      返回頂部
      主站蜘蛛池模板: 99久久www免费人成精品| 亚洲精品456播放| 午夜精品久久久久久影视777 | 久久夜色精品国产噜噜亚洲AV| 国产精品毛片无码| 国产69精品久久久久777| 奇米影视7777久久精品| 亚洲精品第一国产综合境外资源| 国产精品无码v在线观看| 国内精品久久国产大陆| 国产精品亚洲片在线| 中文字幕乱码中文乱码51精品| 精品精品国产理论在线观看| 国产2021久久精品| 麻豆精品成人免费国产片| 国产亚洲色婷婷久久99精品| 最新国产精品拍自在线观看| 四库影院永久四虎精品国产| 久久久WWW成人免费精品| 国产欧美日本精品| 国产成人精品cao在线| 国产精品九九九久久九九| 国产精品伦一区二区三级视频| 久久夜色精品国产噜噜噜亚洲AV| 亚洲av午夜福利精品一区| 中文字幕亚洲精品无码| 亚洲精品无码永久中文字幕| 一本一道久久a久久精品综合| 午夜精品久久久内射近拍高清| 久久亚洲中文字幕精品一区| 久久亚洲国产成人精品无码区| 久久久亚洲精品蜜桃臀| 久久精品无码一区二区三区免费| 国产农村妇女毛片精品久久| 精品国产一区二区三区AV性色| 国产欧美日韩综合精品二区| 精品国产热久久久福利| 久久久精品波多野结衣| 无翼乌无遮挡全彩老师挤奶爱爱帝国综合社区精品 | 亚洲精品无码专区久久久| 亚洲国产一二三精品无码|