2

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

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

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)

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

4

2 回答 2

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

于 2012-05-08T04:06:52.370 回答
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);
    }
}
于 2012-05-08T05:28:48.883 回答