我只是想知道下面的代码中是否出现竞争条件:
int readingFiles;
async Task<string> ReadFile (string file)
{
++readingFiles;
var text = await Stream.ReadFileAsync(file);
--readingFiles;
return text;
}
如果线程池线程执行ReadFile方法,则readFiles将由两个不同的线程访问,而readingFiles变量不受任何同步惯用法的保护。
这意味着对于执行“--readingFiles”的其他线程,readFiles的第一次更新不应该是可见的。但是,在“--readingFiles”之后,我从未见过readFiles等于-1。我检查同一个线程是否使用Thread.CurrentThread执行++和 - 操作。在大多数情况下,它不是同一个线程,我仍然没有看到readingFiles为-1。
即使存在竞争条件且readingFiles不易变,为什么我看不到这种竞争条件的影响?
答案 0 :(得分:10)
这里没有竞争条件。 .NET运行时将插入适当的内存屏障。
另见http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/async-await-faq.aspx
上的评论是的,当任务排队时以及任务执行的开始/结束时,TPL包含适当的障碍,以便适当地使值可见。
答案 1 :(得分:0)
这里有许多事情可以发生。
首先,您运行的是哪种可执行文件?当Await触发时,它使用当前的同步上下文,因此等待的代码可能被序列化为1个UI线程。
此外,由于变量周围没有内存屏障/波动性保护,您的线程可能正在读取单独缓存的值(如@ Spo1ler在其帖子中所述)
此外,线程池可能选择在同一个线程上运行您的请求(它在其权限范围内执行此操作 - 您允许.net / windows决定何时以及如何分配线程)
尽管如此,您确实应该通过同步或互锁操作来保护对变量的访问。