锁定/并发问题

本文关键字:问题 并发 锁定 | 更新日期: 2023-09-27 18:16:33

我有以下c#代码:

1.    List<BandEdge> bandEdgeList;
2.    
3.    bandEdgeList = CicApplication.BandEdgeCache.Where(row => row.Coater == coater).ToList();
4.    foreach (BandEdge bandEdge in bandEdgeList)
5.       {
6.          ...
7.          ...
8.       }
我的问题是这样的。一旦在第3行填充了' banddedgelist ',如果另一个线程修改了CicApplication的内容。banddedgecache, ' banddedgelist '的内容会无效吗?我在CicApplication中有一个锁。banddedgecache getter/setter。但我想知道我是否应该在这段代码周围放一个锁,以便CicApplication的内容。当我使用' banddedgelist '时,banddedgecache不会改变

锁定/并发问题

不是自动的,但这仍然不是线程安全的。它可以抛出一个InvalidOperationException

一旦ToList被调用,它保存这些引用的副本。但如果另一个线程修改BandEdgeCache,而这正在发生,不好的事情发生。

因此,您应该锁定对BandEdgeCache的所有引用。

但是沿着保存列表的行,这将是安全的,但是修改任何BandEdge在没有一些锁定的情况下不是线程安全的。

bandEdgeList将是一个独立的副本(因为您正在使用ToList()),所以您不需要锁定。

但是,正如@Daniel A. White所评论的那样,您需要锁定创建该副本的LINQ语句。

在CicApplication的getter中添加锁。如果banddedgecache返回一个对集合的引用,它将无法帮助您。

CicApplication.BandEdgeCache{
  get{lock(_myCollection){return _myCollection;}}
}

返回引用,但是一旦返回就退出了锁,因此在getter返回的集合的引用上使用Where()函数是在锁之外完成的,并且不是线程安全的。另一个线程可以很高兴地在Where迭代时更改集合,因为锁没有被持有——Daniel是正确的,如果另一个线程在生成列表时更改集合,将抛出InvalidOperationException。

一旦生成了列表,就可以更改原始集合,而不会影响对新列表的访问。