我有一个包含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
}
}
}
解决方法:
这里有两个不同的问题:
>是使用一个组合锁还是两个单独的锁
>是否使用单独的对象锁定或列表本身(或其SyncRoots)
这些在某种程度上是可分离的 – 因为如果你使用两个单独的锁,你可以创建两个单独的对象来锁定,每个列表一个.
如果您希望MethodThatUsesAList和MethodThatUsesBList能够并发运行,则需要两个单独的锁.然后,您必须确保无论何时获得两个锁,您都可以按相同的顺序获取它们.这意味着推理任何获取锁的方法中的所有代码:例如,您需要确保它不会调用另一个获取另一个锁的方法.
如果您的特定场景不太可能受到运行其中任何一个线程的任何一个线程有效阻止其他线程的所有方法的影响,那么为了简单起见,我将使用单个锁.
在任何一种情况下,我都会亲自去寻找其他代码所不知道的“私人”锁.我发现用这种方式编写的代码更容易理由.使用列表本身或同步根可能是绝对正常的 – 但我更喜欢考虑没有其他任何东西可能获得的锁.