我有一个包含 2 个内联列表的类,其中包含超过 1000 个这样的元素,
public class A
{
private List<long> aList = new List<long>();
private List<long> bList = new List<long>();
void MethodThatUsesAList()
{
//Works with aList
}
void MethodThatUsesBList()
{
//Works with bList
}
void MethodThatUsesBoth()
{
//Works with both lists
}
}
现在,我想让这个类线程安全,我看到有两种不同的使用锁的场景,首先是创建
object _synchObject = new object()
并在所有方法中锁定这个对象, 或第二个在使用时锁定每个列表, 我的第一个问题是,首选哪种方法? 如果首选第二个,这样使用锁是否有性能问题?
void MethodThatUsesBoth()
{
lock(aList){
lock(bList){
//Works with both lists
}
}
}
最佳答案
这里有两个不同的问题:
- 使用一把组合锁还是两把分离锁
- 是使用单独的对象来锁定还是使用列表本身(或其
SyncRoot
)
这些在某种程度上是可分离的——因为如果您使用两个单独的锁,您可以创建两个单独的对象来锁定,每个列表一个。
如果您希望 MethodThatUsesAList
和 MethodThatUsesBList
能够同时运行,您将需要两个单独的锁。然后你必须确保任何时候你可能获得两个锁,你获得它们的顺序相同。这意味着对任何获取锁的方法中的所有代码进行推理:例如,您需要确保它不会调用获取另一个锁的另一个方法。
如果您的特定场景不太可能受到所有方法的影响,这些方法被运行任何其中的任何一个线程有效地阻塞其他线程,那么我'为了简单起见,d 使用单个锁。
无论哪种情况,我个人都会选择其他代码不知道的“私有(private)”锁。我发现以这种方式编写的代码更容易推理。使用列表本身或同步根可能绝对没问题 - 但我更愿意考虑其他任何东西都无法获得的锁。
关于c# - 两种不同场景下的锁性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4518295/