Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步/等待代码中的竞争条件_C#_Multithreading_Asynchronous_Async Await_Race Condition - Fatal编程技术网

C# 异步/等待代码中的竞争条件

C# 异步/等待代码中的竞争条件,c#,multithreading,asynchronous,async-await,race-condition,C#,Multithreading,Asynchronous,Async Await,Race Condition,我只是想知道下面的代码中是否出现了竞争条件: int readingFiles; async Task<string> ReadFile (string file) { ++readingFiles; var text = await Stream.ReadFileAsync(file); --readingFiles; return text; } int读取文件; 异步任务读取文件(字符串文件) { ++读取文件; var

我只是想知道下面的代码中是否出现了竞争条件:

int readingFiles;
async Task<string> ReadFile (string file)
{    
    ++readingFiles;

    var text = await Stream.ReadFileAsync(file);

    --readingFiles;

    return text;
}
int读取文件;
异步任务读取文件(字符串文件)
{    
++读取文件;
var text=wait Stream.ReadFileAsync(文件);
--读取文件;
返回文本;
}
如果ReadFile方法由线程池线程执行,则readingFiles将由两个不同的线程访问,并且readingFiles变量不受任何同步习惯用法的保护

这意味着对readingFiles的第一次更新对于执行--“readingFiles”的其他线程不应可见。然而,我从未见过readingFiles在“-readingFiles”之后等于-1。我使用thread.CurrentThread检查同一线程是否执行++和--操作。在大多数情况下,它不是同一个线程,我仍然不认为readingFiles是-1


即使存在竞争条件并且readingFiles不是易失性的,为什么我看不到这种竞争条件的影响呢

这里可能会发生很多事情

首先,您正在运行哪种类型的可执行文件?当wait激发时,它使用当前的同步上下文,因此等待的代码可能会被序列化为一个UI线程

此外,由于变量周围没有内存障碍/波动性保护,线程可能正在读取单独缓存的值(正如@Spo1ler在文章中提到的)

此外,线程池可能会选择在同一个线程上运行两个请求(这样做是在它的权限范围内的——由.net/windows决定何时以及如何分配线程)


但底线是,您确实应该通过同步或联锁操作来保护对变量的访问。

这里没有争用条件。.NET运行时将插入适当的内存屏障

另见以下评论:

是的,TPL在任务排队时以及在任务执行的开始/结束时包括适当的屏障,以便适当地显示值


当然,async/await使用当前同步上下文的整个方式意味着有适当的“同步习惯用法”——你就是看不到它们;睡眠(1000);readingFiles=temp-1您只运行ReadFile的一个实例,对吗?当您调用此方法一次时,没有竞争条件。如果你多次并行调用它(在同一个实例上),它当然是不安全的。所以wait语句是一种记忆障碍。@TomK:是的;它为你解决了记忆障碍。正如Servy提到的,当然您必须小心不要同时从多个线程访问共享数据。