最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

前言

編寫程序的時(shí)候,人們的直觀感覺通常認(rèn)為,程序的執(zhí)行順序是按照語句的順序進(jìn)行的。然而,許多編程語言的規(guī)范是允許實(shí)際執(zhí)行順序與語句編寫順序不符的。實(shí)際上,編譯器為了完成某種優(yōu)化,常常會(huì)對(duì)一些操作進(jìn)行適當(dāng)?shù)捻樞蛘{(diào)整,導(dǎo)致一些預(yù)料之外的現(xiàn)象。

實(shí)驗(yàn)現(xiàn)象

首先,通過一個(gè)例子來展示這個(gè)現(xiàn)象。在一個(gè)C# .NET Core 3.1命令行程序中,定義兩個(gè)全局變量a和b,在線程1中,依次對(duì)b和a進(jìn)行遞增。這樣,在任何時(shí)刻b應(yīng)當(dāng)?shù)扔赼或a+1。

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

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

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

  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}");
      }
    }
  }

再編寫主程序,啟動(dòng)上述的兩個(gè)線程。

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

      Console.ReadKey();
    }

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

查看反匯編可以看到,在第1個(gè)c += b語句處,程序?qū)的值放到了寄存器中,而后面的語句均使用了該寄存器內(nèi)存放的值。所以,編譯器實(shí)際上將對(duì)b的讀取操作合并并且前置了。以下為反匯編結(jié)果片段。

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#語言標(biāo)準(zhǔn)的Basic concepts一章Execution order一節(jié)(參見:Basic concepts – C# language specification)中,提到了C#的執(zhí)行順序規(guī)范。C#程序的副作用在以下關(guān)鍵點(diǎn)處的順序是被保留的:

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

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

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

而上述的副作用包括:

  • 讀取或?qū)懭雟olatile字段
  • 寫入非volatile變量
  • 寫入外部資源
  • 拋出異常

由此可以推出,C#程序中對(duì)非volatile變量的讀取順序可能會(huì)被調(diào)整。在只有一個(gè)線程對(duì)該變量進(jìn)行操作時(shí),這個(gè)順序的調(diào)整是保證不會(huì)影響結(jié)果的;但如果同時(shí)有其他的線程正在對(duì)變量進(jìn)行修改,則讀取的順序是無法確定的。

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

結(jié)論

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

總結(jié)

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

您可能感興趣的文章:

相關(guān)文章

  • C#中List集合使用Max()方法查找到最大值的實(shí)例

    C#中List集合使用Max()方法查找到最大值的實(shí)例

    這篇文章主要介紹了C#中List集合使用Max()方法查找到最大值的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • C#并行編程之Task同步機(jī)制

    C#并行編程之Task同步機(jī)制

    這篇文章介紹了C#并行編程之Task同步機(jī)制,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • C#微信開發(fā)之啟用開發(fā)者模式

    C#微信開發(fā)之啟用開發(fā)者模式

    本文主要介紹了C#微信開發(fā)中啟用開發(fā)者模式的步驟與方法,具有一定的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • C#實(shí)現(xiàn)Ruby的負(fù)數(shù)索引器

    C#實(shí)現(xiàn)Ruby的負(fù)數(shù)索引器

    這篇文章主要介紹了C#實(shí)現(xiàn)Ruby的負(fù)數(shù)索引器的相關(guān)代碼和使用方法,非常簡單實(shí)用,需要的朋友可以參考下
    2016-07-07
  • C#操作windows注冊(cè)表的方法

    C#操作windows注冊(cè)表的方法

    這篇文章主要介紹了C#操作windows注冊(cè)表的方法,涉及C#針對(duì)注冊(cè)表的讀取與寫入技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-04-04
  • C#實(shí)現(xiàn)在線更新軟件

    C#實(shí)現(xiàn)在線更新軟件

    winform程序相對(duì)web程序而言,功能更強(qiáng)大,編程更方便,但軟件更新卻相當(dāng)麻煩,要到客戶端一臺(tái)一臺(tái)地升級(jí),面對(duì)這個(gè)實(shí)際問題,在最近的一個(gè)小項(xiàng)目中,本人設(shè)計(jì)了一個(gè)通過軟件實(shí)現(xiàn)自動(dòng)升級(jí)技術(shù)方案,彌補(bǔ)了這一缺陷,有較好的參考價(jià)值
    2015-05-05
  • c#使用filesystemwatcher實(shí)時(shí)監(jiān)控文件目錄的添加和刪除

    c#使用filesystemwatcher實(shí)時(shí)監(jiān)控文件目錄的添加和刪除

    本文主要描述如何通過c#實(shí)現(xiàn)實(shí)時(shí)監(jiān)控文件目錄下的變化,包括文件和目錄的添加,刪除,修改和重命名等操作
    2014-01-01
  • C#編寫一個(gè)網(wǎng)游客戶端的完整步驟

    C#編寫一個(gè)網(wǎng)游客戶端的完整步驟

    這篇文章主要給大家介紹了關(guān)于C#編寫一個(gè)網(wǎng)游客戶端的相關(guān)資料,文中通過示例代碼以及圖文介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-11-11
  • C#中遍歷Hashtable的4種方法

    C#中遍歷Hashtable的4種方法

    這篇文章主要介紹了C#中遍歷Hashtable的4種方法,本文直接給出實(shí)例代碼,需要的朋友可以參考下
    2015-06-06
  • C#將HashTable中鍵列表或值列表復(fù)制到一維數(shù)組的方法

    C#將HashTable中鍵列表或值列表復(fù)制到一維數(shù)組的方法

    這篇文章主要介紹了C#將HashTable中鍵列表或值列表復(fù)制到一維數(shù)組中方法,涉及C#操作HashTable的相關(guān)技巧,需要的朋友可以參考下
    2015-04-04

最新評(píng)論

长寿区| 山西省| 吉水县| 沅江市| 同德县| 丰镇市| 大名县| 托克逊县| 如皋市| 万载县| 玉环县| 克山县| 太原市| 福贡县| 错那县| 张家界市| 黄梅县| 建平县| 浑源县| 乐昌市| 瓦房店市| 托克托县| 刚察县| 兴仁县| 化德县| 昭觉县| 舒兰市| 壤塘县| 龙江县| 禹州市| 隆德县| 彭泽县| 察哈| 珲春市| 堆龙德庆县| 宜黄县| 河西区| 静安区| 上饶县| 项城市| 泊头市|