欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關于C#執(zhí)行順序帶來的一些潛在問題

 更新時間:2020年08月16日 10:43:10   作者:UWP愛好者  
這篇文章主要給大家介紹了關于C#執(zhí)行順序帶來的一些潛在問題,文中通過示例代碼介紹的非常詳細,對大家學習或者使用C#具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧

前言

編寫程序的時候,人們的直觀感覺通常認為,程序的執(zhí)行順序是按照語句的順序進行的。然而,許多編程語言的規(guī)范是允許實際執(zhí)行順序與語句編寫順序不符的。實際上,編譯器為了完成某種優(yōu)化,常常會對一些操作進行適當的順序調整,導致一些預料之外的現象。

實驗現象

首先,通過一個例子來展示這個現象。在一個C# .NET Core 3.1命令行程序中,定義兩個全局變量a和b,在線程1中,依次對b和a進行遞增。這樣,在任何時刻b應當等于a或a+1。

    static int a = 0;
    static int b = 0;

    static void Thread1()
    {
      while (true)
      {
        ++b;
        ++a;
      }
    }

在線程2中,先讀取a的值,然后執(zhí)行一些其他操作,再讀取b的值。如果語句一定是按順序執(zhí)行的,那么讀取到的b的值應當比讀取到的a的值更新,從而b必然大于或等于a(除非b發(fā)生了溢出)。編寫程序,當b < a時輸出它們的值。

  static int c = 0;

  static void Thread2()
  {
    while (true)
    {
      c += b;
      var localA = a;
      c += b;
      var localB = b;
      if (localA > localB)
      {
        Console.WriteLine($"a={localA} b={localB}");
      }
    }
  }

再編寫主程序,啟動上述的兩個線程。

    static void Main(string[] args)
    {
      Task.Run(Thread1);
      Task.Run(Thread2);

      Console.ReadKey();
    }

使用Debug配置,編譯并運行該程序,命令行是沒有輸出的,符合我們的預期。但是使用Release配置的話,就會出現大量輸出,其中a的值比b大1到5不等。

查看反匯編可以看到,在第1個c += b語句處,程序將b的值放到了寄存器中,而后面的語句均使用了該寄存器內存放的值。所以,編譯器實際上將對b的讀取操作合并并且前置了。以下為反匯編結果片段。

00007FFB628A394D mov     rcx,7FFB6292FBD0h 
00007FFB628A3957 mov     edx,1 
00007FFB628A395C call    00007FFBC2387B10 
00007FFB628A3961 mov     esi,dword ptr [7FFB6292FC08h] 
00007FFB628A3967 mov     ecx,esi 
00007FFB628A3969 add     ecx,dword ptr [7FFB6292FC0Ch] 
00007FFB628A396F mov     dword ptr [7FFB6292FC0Ch],ecx 
        var localA = a;
00007FFB628A3975 mov     edi,dword ptr [7FFB6292FC04h] 
        c += b;
00007FFB628A397B add     ecx,esi 
        c += b;
00007FFB628A397D mov     dword ptr [7FFB6292FC0Ch],ecx 
        if (localA > localB)
00007FFB628A3983 cmp     edi,esi 
00007FFB628A3985 jle     00007FFB628A394D 

理論分析

在C#語言標準的Basic concepts一章Execution order一節(jié)(參見:Basic concepts – C# language specification)中,提到了C#的執(zhí)行順序規(guī)范。C#程序的副作用在以下關鍵點處的順序是被保留的:

  • 對volatile字段的讀寫
  • lock語句
  • 線程的創(chuàng)建和終結

C#程序的執(zhí)行順序在滿足以下條件的情況下,可以由執(zhí)行環(huán)境任意調整的:

  • 在同一線程內,數據的的依賴關系是被保留的。即,結果與語句按照順序執(zhí)行的情況一致。
  • 初始化順序的規(guī)則是被保留的。
  • 相對于volatile字段的讀寫,副作用的順序是被保留的。

而上述的副作用包括:

  • 讀取或寫入volatile字段
  • 寫入非volatile變量
  • 寫入外部資源
  • 拋出異常

由此可以推出,C#程序中對非volatile變量的讀取順序可能會被調整。在只有一個線程對該變量進行操作時,這個順序的調整是保證不會影響結果的;但如果同時有其他的線程正在對變量進行修改,則讀取的順序是無法確定的。

因此,如果有多個線程同時訪問的,對值的實時性有要求的變量,應當設置為volatile變量。將上述實驗中的靜態(tài)變量a和b改為volatile變量后,即使是Release配置下,也不會出現命令行的輸出,即兩個變量的讀取順序符合原始的語句順序。

結論

在C#程序中,讀取非volatile變量的順序可能被執(zhí)行環(huán)境任意調整。如果某個變量在被讀取的時候會被其他線程寫入,為了該讀取結果的實時性,應當將該變量設置為volatile變量。

總結

到此這篇關于關于C#執(zhí)行順序帶來的一些潛在問題就介紹到這了,更多相關C#執(zhí)行順序潛在問題內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關文章

  • C#導航器Xpath與XPathNavigator類

    C#導航器Xpath與XPathNavigator類

    這篇文章介紹了C#導航器Xpath與XPathNavigator類,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • 淺析C#中數組,ArrayList與List對象的區(qū)別

    淺析C#中數組,ArrayList與List對象的區(qū)別

    在C#中,當我們想要存儲一組對象的時候,就會想到用數組,ArrayList,List這三個對象了。那么這三者到底有什么樣的區(qū)別呢
    2013-07-07
  • C#中的異常處理問題try catch finally

    C#中的異常處理問題try catch finally

    這篇文章主要介紹了C#中的異常處理問題try catch finally,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • C#?CefSharp?根據輸入日期段自動選擇日期的操作代碼

    C#?CefSharp?根據輸入日期段自動選擇日期的操作代碼

    這篇文章主要介紹了C#?CefSharp?根據輸入日期段自動選擇日期的操作代碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-01-01
  • c#和net存取cookies操作示例

    c#和net存取cookies操作示例

    這篇文章主要介紹了c#和net存取cookies操作示例,需要的朋友可以參考下
    2014-02-02
  • c#通過DES加密算法加密大文件的方法

    c#通過DES加密算法加密大文件的方法

    這篇文章主要介紹了c#通過DES加密算法加密大文件的方法,涉及C#文件操作與DES加密的相關技巧,需要的朋友可以參考下
    2015-05-05
  • Unity切割圖集轉換為多張圖片

    Unity切割圖集轉換為多張圖片

    這篇文章主要為大家詳細介紹了Unity切割圖集轉換為多張圖片,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • c#異步task示例分享(異步操作)

    c#異步task示例分享(異步操作)

    這篇文章主要介紹了c#異步task示例(異步操作),需要的朋友可以參考下
    2014-03-03
  • C#比較時間大小的方法總結

    C#比較時間大小的方法總結

    在本篇內容里小編給大家分享的是關于C#比較時間大小的方法總結,對此有需要的朋友們可以學習下。
    2018-12-12
  • C#實現騎士飛行棋

    C#實現騎士飛行棋

    這篇文章主要為大家詳細介紹了C#實現騎士飛行棋,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02

最新評論