方法#1:
最简单且效率最低的方法是为读者和作者创建一个临界区。
// Writer
lock (aList)
{
aList.Remove(item);
}
// Reader
lock (aList)
{
foreach (T name in aList)
{
name.doSomething();
}
}
方法#2:
这类似于方法#1,但不是在整个foreach
循环期间保持锁定,而是先复制集合,然后遍历副本。
// Writer
lock (aList)
{
aList.Remove(item);
}
// Reader
List<T> copy;
lock (aList)
{
copy = new List<T>(aList);
}
foreach (T name in copy)
{
name.doSomething();
}
方法#3:
这完全取决于您的具体情况,但我通常处理此问题的方式是保持对集合的主引用不可变。这样,您就不必在阅读器端同步访问。作家方面需要一个lock
. 读者端什么都不需要,这意味着读者保持高度并发。您唯一需要做的就是将aList
引用标记为volatile
.
// Variable declaration
object lockref = new object();
volatile List<T> aList = new List<T>();
// Writer
lock (lockref)
{
var copy = new List<T>(aList);
copy.Remove(item);
aList = copy;
}
// Reader
List<T> local = aList;
foreach (T name in local)
{
name.doSomething();
}