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

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

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

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

      上一章我們學(xué)習(xí)了原子操作Interlocked類的幾個常用方法,今天我們將繼續(xù)學(xué)習(xí)該類的其他方法。

      01、Exchange方法

      該方法用于原子的將變量的值設(shè)置為新值,并返回變量的原始值。該方法共有14個重載方法,其中13個為常見的數(shù)據(jù)類型,有1個為泛型版本。

      我們可以根據(jù)該方法可以原子更新一個變量并且可以同時獲取該變量舊值這一特性,設(shè)計一個簡單的鎖機制,大致思路如下:

      1.定義一個標志位,如果該標志位舊值為0表示當(dāng)前線程獲取鎖,否則表示當(dāng)前線程無法獲取鎖;

      2.當(dāng)線程獲取鎖后,可以進行業(yè)務(wù)處理,安全的處理非線程安全資源訪問的代碼;

      3.當(dāng)線程處理完業(yè)務(wù)后,釋放鎖,即更新標志位值為0,當(dāng)前線程則退出鎖,其他線程可以繼續(xù)獲取鎖;

      實現(xiàn)代碼如下;

      //0 表示未鎖定,1 表示鎖定
      private static long _exchangeValue = 0;
      public static void ExchangeRun()
      {
          var rnd = new Random();
          //啟動10個線程
          var threads = new Thread[10];
          for (var j = 0; j < threads.Length; j++)
          {
              threads[j] = new Thread(ModifyExchangeValue);
              threads[j].Start();
              //等待一段隨機的時間后再開始啟動另一個線程
              Thread.Sleep(rnd.Next(0, 100));
          }
      }
      static void ModifyExchangeValue()
      {
          //更新_exchangeValue為1,同時獲取_exchangeValue舊值
          var oldExchangeValue = Interlocked.Exchange(ref _exchangeValue, 1);
          //如果舊值為0,表示該邏輯未被其他線程占用
          if (0 == oldExchangeValue)
          {
              //當(dāng)前線程開始鎖定該代碼塊,其他線程無法進入
              Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} 線程 進入鎖");
              //模擬一些工作
              //這里可以實現(xiàn)安全的處理非線程安全資源訪問的代碼
              Thread.Sleep(100);
              //釋放鎖
              Interlocked.Exchange(ref _exchangeValue, 0);
              //當(dāng)前線程釋放完鎖,其他線程可以進入該代碼塊
              Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} 線程 退出鎖");
          }
          else
          {
              Console.WriteLine($"    {Thread.CurrentThread.ManagedThreadId} 線程 無法進入鎖");
          }
      }
      

      我們可以看看執(zhí)行結(jié)果:

      可以發(fā)現(xiàn)當(dāng)一個線程獲取鎖后,其他線程則無法再獲取該鎖,只有當(dāng)前線程處理完成業(yè)務(wù)退出改鎖后,其他線程才可以繼續(xù)獲取該鎖。

      02、Exchange方法

      該方法是Exchange方法的泛型版本,具體使用可以參考上一節(jié)。

      03、CompareExchange方法

      該方法用于原子的比較第一個變量和第三個變量是否相等,如果相等,則將第一個變量替換為第二個變量值,并返回第一個變量的原始值;該方法也有14個重載方法,其中13個為常見的數(shù)據(jù)類型,有1個為泛型版本。

      可以理解為該方法比Exchange方法多了一個條件判斷。因此該方法可以應(yīng)用于更復(fù)雜的業(yè)務(wù)場景。

      下面我們就使用該方法實現(xiàn)CAS(Compare and Swap)算法,并實現(xiàn)一個簡單的版本控制功能。

      所謂版本控制就是指使用一個版本號來表示對象的狀態(tài),每次更新該對象時,我們都希望確保只有當(dāng)當(dāng)前版本號與我們預(yù)期的版本號一致時才能執(zhí)行更新操作。否則,說明在這期間有其他線程更新了該對象,我們需要放棄當(dāng)前操作或者重試。

      首先我們需要構(gòu)建一個版本化數(shù)據(jù)類,該類中有兩個字段用于分別用于存儲數(shù)據(jù)和版本號;并提供兩個方法,一個方法用于獲取當(dāng)前數(shù)據(jù)和版本號,一個方法用于通過版本號更新數(shù)據(jù)。具體實現(xiàn)代碼如下:

      //版本化數(shù)據(jù)
      public class VersionedData<T>(T data)
      {
          private T _data = data;
          private long _version = 0;
          //獲取當(dāng)前數(shù)據(jù)和版本號
          public (T Data, long Version) GetData()
          {
              return (_data, _version);
          }
          //基于版本號嘗試更新數(shù)據(jù)
          public bool TryUpdateData(T data, long expectedVersion)
          {
              //如果_version與預(yù)期版本號相同,
              //則對預(yù)期版本號加1后再替換為_version,
              //同時返回_version舊值
              var oldVersion = Interlocked.CompareExchange(ref _version, expectedVersion + 1, expectedVersion);
              //如果_version舊值與預(yù)期版本號相同
              if (oldVersion == expectedVersion)
              {
                  //則版本號匹配,更新數(shù)據(jù)
                  _data = data;
                  return true;
              }
              //否則版本號不匹配,更新失敗
              return false;
          }
      }
      

      完成版本化類設(shè)計后,就可以使用了,我們模擬兩個線程,同時獲取當(dāng)前版本化數(shù)據(jù)和版本號,然后同時再更新數(shù)據(jù),具體代碼如下:

      public static void CompareExchangeRun()
      {
          var versionedData = new VersionedData<string>("初始化數(shù)據(jù)");
          //線程 1 嘗試更新數(shù)據(jù)
          var thread1 = new Thread(ModifyCompareExchangeValue);
          //線程 2 嘗試更新數(shù)據(jù)
          var thread2 = new Thread(ModifyCompareExchangeValue);
          thread1.Start(versionedData);
          thread2.Start(versionedData);
          thread1.Join();
          thread2.Join();
          //最終結(jié)果
          var (finalData, finalVersion) = versionedData.GetData();
          Console.WriteLine($"最終數(shù)據(jù)為 [{finalData}], 最終版本號為 [{finalVersion}]");
      }
      static void ModifyCompareExchangeValue(object param)
      {
          var threadId = Thread.CurrentThread.ManagedThreadId;
          var versionedData = (VersionedData<string>)param;
          var (data, version) = versionedData.GetData();
          Console.WriteLine($"線程 {threadId} : 當(dāng)前數(shù)據(jù)為 [{data}], 當(dāng)前版本號為 [{version}]");
          Console.WriteLine("---------------------------------------------------");
          var newData = $"線程 {threadId} 數(shù)據(jù)";
          var success = versionedData.TryUpdateData(newData, version);
          Console.WriteLine($"線程 {threadId} 更新數(shù)據(jù): [{(success ? "成功" : "失敗")}]");
          Console.WriteLine($"    數(shù)據(jù)預(yù)期更新為:[{newData}]");
          Console.WriteLine($"    版本號預(yù)期更新為:[{version + 1}]");
          Console.WriteLine("---------------------------------------------------");
      }
      

      我們來看看執(zhí)行結(jié)果:

      通過結(jié)果可以發(fā)現(xiàn)只有1個線程更新成功了。

      04、CompareExchange方法

      該方法是CompareExchange方法的泛型版本,具體使用可以參考上一節(jié)。

      05、And方法

      該方法用于原子的對兩個變量進行按位與操作,將第一個變量替換為操作結(jié)果,并返回第一個變量的原始值;該方法同樣有4個重載方法,分別為long、ulong、int和uint四種數(shù)據(jù)類型;

      主要還是用于多線程環(huán)境下,對共享變量進行安全的原子性按位與操作,避免并發(fā)修改時可能出現(xiàn)的數(shù)據(jù)不一致問題。

      下面看一個簡單的例子:

      public static void AndRun()
      {
          var a = 10; // 二進制: 1010
          var b = 5; // 二進制: 0101
          var oldA = Interlocked.And(ref a, b);
          //1010 & 0101 = 0000 = 0
          Console.WriteLine("操作后的值: " + a); 
          Console.WriteLine("返回的結(jié)果: " + oldA); 
      }
      

      看看執(zhí)行結(jié)果;

      可以理解為就是兩個數(shù)進行按位與運算,并且可以原子的更新原值,并返回原始值。

      06、Or方法

      該方法用于原子的對兩個變量進行按位或操作,將第一個變量替換為操作結(jié)果,并返回第一個變量的原始值;該方法也有4個重載方法,分別為long、ulong、int和uint四種數(shù)據(jù)類型;

      具體使用可以參考And方法。

      07、MemoryBarrier方法

      該方法用于強制執(zhí)行內(nèi)存屏障,作用范圍當(dāng)前線程,無返回值。后面有機會我們再詳細講解。

      08、MemoryBarrierProcessWide方法

      該方法用于提供進程范圍的內(nèi)存屏障,確保任何 CPU 的讀取和寫入無法跨屏障移動。后面有機會我們再詳細講解。

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

      posted @ 2025-02-08 17:08  IT規(guī)劃師  閱讀(600)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 亚洲最大成人av在线天堂网| 无码日韩做暖暖大全免费不卡| 福利在线视频一区二区| 日韩精品人妻中文字幕| 亚洲丰满熟女一区二区蜜桃| 9久久伊人精品综合| 久久亚洲精品成人综合网| 久久亚洲精品无码va白人极品| 美腿丝袜亚洲综合第一页| 丁香五月婷激情综合第九色| 四虎在线播放亚洲成人| 亚洲AV永久中文无码精品综合| 诱人的老师hd中文字幕| 亚洲老女人区一区二视频| 色欲久久久天天天综合网精品| 国产午夜福利视频第三区| 香港日本三级亚洲三级| 日本少妇自慰免费完整版| 国产人妇三级视频在线观看| 另类图片亚洲人妻中文无码 | 成人特黄A级毛片免费视频| 鲁一鲁一鲁一鲁一澡| 无码人妻精品一区二区三区蜜桃| 国产一区二区三区AV在线无码观看| 亚洲日韩乱码中文无码蜜桃臀| 久久精品无码免费不卡| 国产乱色国产精品免费视频| 久久99久国产精品66| 中文字幕第一页亚洲精品| 北条麻妃一区二区三区av高清| 国产激情一区二区三区四区| 亚洲欧洲日韩国内精品| 丰满的少妇被猛烈进入白浆| 国产成人av免费观看| 亚洲国产成人字幕久久| 国产精品久久毛片| 波多野结衣美乳人妻hd电影欧美| 啦啦啦视频在线日韩精品| 国产网友愉拍精品视频手机| 久久精品国产亚洲AV麻豆长发| 国产91色综合久久免费|