锁定公共对象,并跨模块共享

时间:2012-05-08 03:49:35

标签: c# multithreading concurrency blocking

我正在审查一些代码,并看到了我以前从未见过的东西。我找到了一个用于锁定的对象的所有引用,并得到了以下结果。

我已经替换了所有文件/类/成员名称,以保护那些可能需要保护的人。

C:\Sln1\ProjX\ClassX.cs - (17, 26) : public static object PublicStaticLockObj = new object();
C:\Sln1\Proj1\Class1.cs - (193, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj1\Class1.cs - (228, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj1\Class1.cs - (92, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj2\Class2.cs - (115, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj2\Class2.cs - (181, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj2\Class2.cs - (216, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj3\Class3.cs - (160, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj3\Class3.cs - (195, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj3\Class3.cs - (95, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj4\Class4.cs - (133, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj4\Class4.cs - (252, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj4\Class4.cs - (286, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj5\Class5.cs - (252, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj5\Class5.cs - (320, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj5\Class5.cs - (360, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj6\Class6.cs - (112, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj6\Class6.cs - (177, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj6\Class6.cs - (212, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj7\Class7.cs - (165, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj8\Class8.cs - (129, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj8\Class8.cs - (198, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj8\Class8.cs - (233, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj9\Class9.cs - (156, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj9\Class9.cs - (191, 20) : lock (ClassX.PublicStaticLockObj)
C:\Sln1\Proj9\Class9.cs - (90, 20) : lock (ClassX.PublicStaticLockObj)

是否存在跨模块共享锁定是解决问题的好方法?是否有关于锁定公共对象的指导?

2 个答案:

答案 0 :(得分:5)

如果代码闻起来,那就是臭气熏天。

作为同步机制的锁的主要弱点是它们不可编辑 - 需要很容易地获取多个锁导致死锁。

防止死锁的唯一方法是将锁定的情况限制在绝对必要的位置,并限制在锁定时执行的操作,例如:避免做任何可能需要另外锁定的事情,但也避免做任何可以阻塞,睡眠或花费很长时间的事情,因为现在有效地提升了所需的任何操作 - 它可以同时阻止多个线程!

将锁定公开是一种鼓励开发人员采取他们真正不需要采取的锁定的方法,或者他们确实没有考虑采取的后果。

你可能想要一个比我更官方的参考!试试'lock'语句文档。

  

通常,避免锁定公共类型或超出代码控制范围的实例。常见的构造锁(this),lock(typeof(MyType))和lock(“myLock”)违反了这条准则:

     如果可以公开访问实例,则

lock(this)是一个问题。

     如果MyType可公开访问,则

lock(typeof(MyType))是一个问题。

     

lock(“myLock”)是一个问题,因为进程中任何其他代码使用相同的字符串,都会共享同一个锁。

     

最佳做法是定义要锁定的私有对象,或私有静态对象变量以保护所有实例共有的数据。

来源:http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.80).aspx

答案 1 :(得分:2)

PublicStaticLockObject可能用于同步对某些PublicStaticResource的访问,在这种情况下,如果每个人都能很好地使用该对象,那么您就不会遇到麻烦。但是,如果有人将该锁定对象用于不同的资源,则存在死锁的风险。另请注意,该对象不是只读的,因此有人可以用新对象替换它。这也可能会带来麻烦。

这就是为什么ClassX应该声明一个私有锁对象,然后通过公共静态方法公开公共静态资源;这些方法将包含用于保护资源的锁定语句。例如,之前:

public static class ClassX
{
    public static FileStream Stream { get; private set; }
    public static object PublicStaticLockObj = new object();
}

public class ClassY
{
    public void WriteToTheGlobalStream(byte b)
    {
        lock (ClassX.PublicStaticLockObj)
            ClassX.Stream.WriteByte(b);
    }
}

后:

public static class ClassX
{
    private static FileStream Stream { get; set; }
    private static object PublicStaticLockObj = new object();
    public static void WriteToTheStream(byte b)
    {
        lock (PublicStaticLockObj)
            Stream.WriteByte(b);
    }
}

public class ClassY
{
    public void WriteToTheGlobalStream(byte b)
    {
        ClassX.WriteToTheStream(b);
    }
}