<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      并發(fā)編程 - 線程同步(四)之原子操作Interlocked詳解一

      上一章我們了解了原子操作Interlocked類的設(shè)計(jì)原理及簡(jiǎn)單介紹,今天我們將對(duì)Interlocked的使用進(jìn)行詳細(xì)講解。

      在此之前我們先學(xué)習(xí)一個(gè)概念——原子操作。

      01、Read方法

      該方法用于原子的讀取64位值,有分別針對(duì)long類型和ulong類型的兩個(gè)重載方法;

      對(duì)于64位系統(tǒng),64位數(shù)據(jù)類型的讀取本身就是原子操作;而對(duì)于32位系統(tǒng),64位數(shù)據(jù)類型的讀取需要至少兩個(gè)原子指令,因此在32位系統(tǒng)可以通過Read方法對(duì)64位數(shù)據(jù)類型進(jìn)行原子讀取。

      用法也很簡(jiǎn)單,示例如下:

      private static long _readValue = 0;
      public static void ReadRun()
      {
          var thread = new Thread(ModifyReadValue);
          thread.Start();
          Thread.Sleep(100);
          var value = Interlocked.Read(ref _readValue);
          Console.WriteLine("原子讀取long類型變量: " + value);
      }
      static void ModifyReadValue()
      {
          _readValue = 88;
          Console.WriteLine("修改long類型變量: " + _readValue);
      }
      

      運(yùn)行結(jié)果如下:

      因?yàn)橄到y(tǒng)環(huán)境原因無法模擬出32位系統(tǒng)效果,因此這里只是給了個(gè)簡(jiǎn)單使用示例。

      02、Increment方法

      該方法用于原子的遞增指定的變量,并返回遞增后的新值。該方法有4個(gè)重載方法,分別為long、ulong、int和uint四種數(shù)據(jù)類型;該方法適用于多線程環(huán)境中需要安全遞增變量的場(chǎng)景,如計(jì)數(shù)器、資源管理等。

      對(duì)于加法操作,無論是i+1,還是i++或++i,都不是線程安全的,最終可能會(huì)生成3條CPU指令,整個(gè)操作過程大致如下:

      1.將 i 的值加載到寄存器,即從內(nèi)存中讀取i;

      2.將寄存器中值加1,即i值加1;

      3.最后將寄存器中值回寫到i,即完成i值的變更;

      而在這編碼層面為1行代碼,而CPU層面為3行指令的操作中,隨時(shí)都有可能被線程調(diào)度器打斷,而導(dǎo)致其他線程同時(shí)對(duì)i進(jìn)行操作,最終導(dǎo)致競(jìng)爭(zhēng)條件,最后數(shù)據(jù)錯(cuò)亂。

      下面我們來舉個(gè)例子,啟動(dòng)100個(gè)線程,分別對(duì)一個(gè)共享變量進(jìn)行1000次遞增1,最后打印出共享變量,運(yùn)行這個(gè)示例9次觀察每次運(yùn)行結(jié)果,代碼如下:

      private static long _incrementValue = 0;
      public static void IncrementRun()
      {
          //運(yùn)行9次測(cè)試,觀察每次結(jié)果
          for (var i = 1; i < 10; i++)
          {
              //啟動(dòng)100個(gè)線程,對(duì)變量進(jìn)行遞增
              var threads = new Thread[100];
              for (var j = 0; j < threads.Length; j++)
              {
                  threads[j] = new Thread(ModifyIncrementValue);
                  threads[j].Start();
              }
              //等待所有線程執(zhí)行完成
              foreach (var thread in threads)
              {
                  thread.Join();
              }
              //最后打印結(jié)果
              Console.WriteLine($"第 {i} 運(yùn)行結(jié)果: {_incrementValue}");
              _incrementValue = 0;
          }
      }
      static void ModifyIncrementValue()
      {
          for (var i = 0; i < 1000; i++)
          {
              ++_incrementValue;
          }
      }
      

      先看下執(zhí)行結(jié)果:

      可以發(fā)現(xiàn)每次的運(yùn)行結(jié)果都不相同,并且結(jié)果也不對(duì)。這就是因?yàn)?+i操作并不是原子操作,是線程不安全的。

      只需要把上面代碼:

      ++_incrementValue;
      

      改為:

      Interlocked.Increment(ref _incrementValue);
      

      即可解決上面的問題,修改過后,我們?cè)賮砜纯磮?zhí)行結(jié)果:

      03、Decrement方法

      該方法用于原子的遞減指定的變量,并返回遞減后的新值。該方法同樣有4個(gè)重載方法,分別為long、ulong、int和uint四種數(shù)據(jù)類型;

      該方法和Increment方法基本一樣,區(qū)別就是一個(gè)是遞增一個(gè)是遞減,因此用法可以直接參考Increment方法,這里就不做詳細(xì)講解了。

      04、Add方法

      該方法用于原子的對(duì)兩個(gè)變量求和,將第一個(gè)變量替換為兩者和,并返回操作后第一個(gè)變量的新值。該方法同樣有4個(gè)重載方法,分別為long、ulong、int和uint四種數(shù)據(jù)類型;

      雖然這個(gè)方法叫求和是加法,但是只需要把第2個(gè)參數(shù)變?yōu)樨?fù)數(shù),既可以實(shí)現(xiàn)減法。簡(jiǎn)單來說該方法可以實(shí)現(xiàn)原子的對(duì)兩個(gè)變量求和與求差。

      上面Increment方法和Decrement方法,只能對(duì)變量每次進(jìn)行遞增遞減1,而能隨意加減,可以通過Add方法實(shí)現(xiàn)兩個(gè)變量進(jìn)行加減。

      下面我們用代碼實(shí)現(xiàn)累加和累減示例用來說明Add使用方法,就不展示線程安全差異了,可以參考Increment方法中的示例,自己寫一個(gè)線程不安全的示例。

      private static long _addValue = 0;
      public static void AddRun()
      {
          for (var j = 0; j < 1000; j++)
          {
              //_addValue =_ addValue + j;
              Interlocked.Add(ref _addValue, j);
          }
          Console.WriteLine($"累加結(jié)果: {_addValue}");
          _addValue = 0;
          for (var j = 0; j < 1000; j++)
          {
              //_addValue =_ addValue - j;
              Interlocked.Add(ref _addValue, -j);
          }
          Console.WriteLine($"累減結(jié)果: {_addValue}");
      }
      

      執(zhí)行結(jié)果如下:

      :測(cè)試方法代碼以及示例源碼都已經(jīng)上傳至代碼庫,有興趣的可以看看。https://gitee.com/hugogoos/Planner

      posted @ 2025-02-07 09:38  IT規(guī)劃師  閱讀(734)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 超碰成人人人做人人爽| 姐姐6电视剧在线观看| 综合色天天久久| 婷婷四虎东京热无码群交双飞视频 | 办公室强奷漂亮少妇视频| 天天狠天天透天天伊人| 久久人妻国产精品| 午夜国产精品福利一二| 777米奇影视第四色| 国产伦一区二区三区视频| 激情综合网激情五月伊人| 亚洲乱码精品久久久久..| 天天色综网| 免费无码成人AV片在线| 四虎永久免费很黄的视频| 中文字幕免费不卡二区| 老熟妇老熟女老女人天堂| 午夜大尺度福利视频一区| 在线视频不卡在线亚洲| 中文字幕第一页国产| 夜夜嗨久久人成在日日夜夜| 年轻女教师hd中字3| 亚洲乱码国产乱码精品精| 中文字幕国产精品一二区| 国产又色又爽又刺激在线观看| 国产精品日韩中文字幕熟女| 性饥渴少妇AV无码毛片| 无码人妻丝袜在线视频| 三级黄色片一区二区三区| 少妇性l交大片| 国产精品老熟女一区二区| 亚洲欧美日韩精品久久| 中文字幕人妻精品在线| 不卡一区二区三区四区视频| 国产午夜一区二区在线观看| 精品人妻中文字幕有码在线| 精品无码国产污污污免费| 强奷乱码欧妇女中文字幕熟女| 网友自拍视频一区二区三区| 亚洲男人的天堂一区二区| 蜜臀久久精品亚洲一区|