自從我閱讀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