我有一个包含项目集合的对象。我希望能够通过AddItem方法将项添加到集合中,并且还可以遍历集合中的所有项。我的对象必须是线程安全的。我正在使用ReaderWriterLockSlim来确保正确的同步。 我应该如何同步GoThroughAllItems方法?我应该在整个持续时间内启动一个大的ReadLock,这可能会很长,或者我应该为从集合中提取的每个项目释放锁定,并为下一个重新获取锁定吗?
以下是一些示例代码:
private ReaderWriterLockSlim @lock = new ReaderWriterLockSlim(); private List items = new List(); public void AddItem(Item item) { this.@lock.EnterWriteLock(); try { //do something with item and add it to the collection this.items.Add(item); } finally { this.@lock.ExitWriteLock(); } } public void GoThroughAllItems() { this.@lock.EnterReadLock(); try { foreach (Item item in this.Items) { #if option2 this.@lock.ExitReadLock(); #endif //process item, which may take a long time #if option2 this.@lock.EnterReadLock(); #endif } } #if option2 catch #endif #if option1 finally #endif { this.@lock.ExitReadLock(); } }
答案 0 :(得分:0)
这里最好的方法是创建一个集合副本,然后迭代它。它有很大的内存开销(但很快就会发布)。
伪代码:
read lock
foreach oldColl
populate newColl
exit lock
foreach newColl
do things
并且每个项目的锁定代码都不起作用,因为其他线程可能会修改集合并且会导致错误,因为foreach不允许修改集合。
答案 1 :(得分:0)
我只是选择你的第一个选项与foreach周围的读取区域,因为在读取块中允许多个线程,它并不重要,因为它相当慢。另一方面,独占写操作非常快。所以这应该是一个很好的解决方案。