这是使自定义类型线程安全的有效方法吗?和一般线程问题

ran*_*gui -1 c# multithreading c#-4.0

在处理线程时我有一些一般性的问题.我一直在环顾四周,但没有真正看到我的问题的任何答案

当你想要在类中处理多个变量时,你想要是线程安全的,你是否应该为你想锁定在类中的每个变量都有一个"锁定对象"?像这样?

static readonly object lockForVarA = new object();
private float varA;

static readonly object lockForVarB = new object();
private float varB;
Run Code Online (Sandbox Code Playgroud)

这也是处理自定义类型的线程安全的有效方法吗?

public class SomeClass
{
    public SomeClass()
    {
       //Do some kind of work IE load an assembly
    }
}


public class SomeOtherClass : BaseClassFiringFromRandomThread
{
    static readonly object someClassLock = new object();
    SomeClass someClass;
    public override void Init()//this is fired from any available thread, can be fired multiple times and even at the same time
    {
        lock(someClassLock)
        {
            if(someClass == null)
                someClass = new SomeClass();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码位于类的构造函数中,可以随时从任何线程调用

Eri*_*ert 5

当你想要在类中处理多个变量时,你想要是线程安全的,你是否应该为你想锁定在类中的每个变量都有一个"锁定对象"?

有两个规则:

  • 要"细粒度".拥有尽可能多的锁,每个变量一个.每次使用时都可以访问锁定下的变量.锁定尽可能少的代码以确保可伸缩性.如果您忘记锁定变量,您将导致竞争条件,如果您的锁定顺序错误,您将导致死锁,因此请确保您完美无缺.
  • 是"粗粒度".只有一个锁,并将所有关键部分放在该锁下.拥有多个锁可以减少争用,但会增加死锁和其他错误的可能性,因此尽可能少地使用锁,每个锁中尽可能多的代码.当然,这也增加了死锁的风险,因为现在锁内部有更多的代码可以进行反转,并且会降低可伸缩性.

毫无疑问,标准建议是完全矛盾的.那是因为锁很糟糕.

我的建议:如果你不跨线程共享变量,那么你根本不需要任何锁.

这也是处理自定义类型的线程安全的有效方法吗?

到目前为止,代码看起来很合理,但如果您的意图是延迟加载某些逻辑,那么就不要编写自己的线程逻辑.只需使用Lazy<T>并使其完成工作.它是由专家撰写的.

始终使用专家设计的最高级别工具.滚动自己的线程原语是灾难的一个方法.

无论你做什么都不接受另一个答案的建议,你必须使用双重检查锁定.在任何情况下都不得使用双重检查锁定.单次检查锁定更安全,更容易,更可能是正确的.只有当(1)你有大量的经验证据表明争用是导致可测量的,影响用户的性能问题的原因时才使用双重检查锁定,这个问题将通过低锁来解决,(2)你可以解释什么规则在C#内存模型使双重检查锁定安全.

如果你做不到(1)那么你没有理由进行双重检查锁定,如果你做不到(2),你就无法安全地做到这一点.