自从我阅读Jon Skeet的site上的迭代器后,这只是让我感到困惑。为什么c#迭代器使用互锁操作跟踪创建线程?
微软用自动迭代器实现了一个简单的性能优化 - 返回的IEnumerable可以作为IEnumerator重用,保存对象的创建。现在因为IEnumerator需要跟踪状态,所以只有在第一次迭代时才有效。
我不明白的是为什么设计团队采取了他们确保线程安全的方法。
通常当我处于类似的位置时,我会使用我认为是简单的Interlocked.CompareExchange--确保只有一个线程设法将状态从“可用”更改为“正在处理”。
概念上它是非常简单的,单一的原子操作,不需要额外的字段等等
但设计团队的做法?每个IEnumerable都保留创建线程的托管线程ID的字段,然后在调用GetEnumerator时检查该线程ID是否对该字段进行检查,并且只有它是相同的线程,并且它是第一次调用时,IEnumerable是否可以返回自身作为IEnumerator。这似乎很难推理,伊莫。
我只是想知道为什么采取这种方法。 Interlocked操作比两次调用System.Threading.Thread.CurrentThread.ManagedThreadId要慢得多,以至于证明额外的字段是正确的?
还是有其他原因背后,也许涉及内存模型或ARM设备或我没有看到?也许这个规范给IEnumerable的实现提供了特定的要求?只是真正困惑。
这很有道理,谢谢。我想我的印象是联锁操作仍然相对便宜 - 我一直认为分配(即首先是IEnumerable)必须至少包含一个锁定的加法。如果它们非常昂贵,我现在意识到每个线程都可能被分配到一个小池中,以便不需要互锁操作等等。我也错误地认为Thread.CurrentThread可能不是最便宜的程序 - 尽管VS不会让我介入它,我愿意接受它很快。 Ty :) – Mania