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

C# 锁定公共对象,并跨模块共享,c#,multithreading,concurrency,blocking,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

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

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

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)

是否曾经有过这样一种情况:跨模块共享锁是解决问题的好方法?有关于锁定公共对象的指导吗?

如果代码有异味,就会有异味

锁作为同步机制的主要缺点是它们不可组合-需要获取多个锁很容易导致死锁

防止死锁的唯一方法是将获取锁的情况限制在绝对必要的情况下,并限制在持有锁时执行的操作,例如,避免执行任何可能占用另一个锁的操作,也避免执行任何可能阻塞、睡眠或长时间占用的操作,因为任何需要这么长时间的操作现在都已经有效地升级了——它可以一次阻止多个线程

公开锁是一种鼓励开发人员使用他们确实不需要的锁,或者他们确实没有考虑使用锁的后果的方法

你可能想要比我更正式的推荐人!请尝试“锁定”语句文档

通常,避免锁定公共类型或代码无法控制的实例。常见的构造lock(this)、lock(typeof(MyType))和lock(“myLock”)违反了以下准则:

如果可以公开访问实例,则锁定(这)是一个问题

如果MyType是可公开访问的,则锁(typeof(MyType))是一个问题

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

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


来源:

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);
    }
}

似乎在代码中的很多地方都有一个强大的锁对象。闻起来有点腥味。所有这些锁都是保护单个数据结构还是将这些锁用于一组不相关的结构?正如其他人所说,这很可能是个坏主意,但没有上下文说明它们锁定/序列化的内容,很难推荐一种特定的模式/方法来替换它。如果你要这样做,那么你最好做
lock(typeof(ClassX))
…其实差别不大。