2013-07-30 34 views
1

我知道何时在C#中使用锁定块,但是我不清楚的是锁定语句括号中的lock variable。考虑以下Singleton Design PatternDoFactory:在上面的代码C#中的锁定变量#

class LoadBalancer 
{ 
    private static LoadBalancer _instance; 
    private List<string> _servers = new List<string>(); 
    private static object syncLock = new object(); 
    public static LoadBalancer GetLoadBalancer() 
    { 
    // Support multithreaded applications through 
    // 'Double checked locking' pattern which (once 
    // the instance exists) avoids locking each 
    // time the method is invoked 
    if (_instance == null) 
    { 
    lock (syncLock) 
    { 
     if (_instance == null) 
     { 
     _instance = new LoadBalancer(); 
     } 
    } 
    } 

    return _instance; 
} 
} 

,我不明白为什么我们不锁变量,而不是`SYNCLOCK使用_instance

回答

12

在上面的代码中,我不明白为什么我们不使用_instance作为lock变量而不是`syncLock?

那么你会试图锁定一个空引用,一方面...

此外,你会通过可变的领域,这是一个坏主意来锁定。 (如果字段更改值,则另一个线程可以进入相同的代码,但不是很好)。通过只读字段进行锁定通常是个好主意。

此外,你会锁定一个参考,这是返回给调用者,谁可以持有任意长时间的锁。我更喜欢锁定一个永远不会暴露在课堂外的参考 - 比如syncLock

最后,由于CLI内存模型的原因,这种实现方式仍然存在问题。 (它的可能是或者可能不会在MS实现中被打破,这是更强一点。我不想打赌任何一种方式。)_instance变量应该被标记为volatile如果你真的想要使用这种方法...但我个人会避免重复检查锁定。请参阅我的article on the singleton pattern了解更多详情。

+0

为什么编译器使用syncLock?这个变量有什么好处? –

+0

@SeyedMortezaMousavi:你是什么意思“为什么编译器使用syncLock?”它不是编译器,它是开发人员......关键是确保只有一个线程输入创建LoadBalancer实例的代码。 –

+2

你需要锁定一个对象。这就是它的全部。 –

0

我自己并没有多使用锁定语句。

但我的猜测是,这是因为你无法锁定实例,因为它是空的。

因此,您必须制作静态对象“synclock”,该对象仅用于锁定实际创建“实例”变量的部分。