猿问

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

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


当您要在一个线程中处理一个类中的多个变量时,是否应该为要锁定在该类中的每个变量都拥有一个“锁定对象”?像这样?


static readonly object lockForVarA = new object();

private float varA;


static readonly object lockForVarB = new object();

private float varB;

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


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

        }

    }

}

这段代码位于一个类的构造函数中,该类可以随时从任何线程调用


收到一只叮咚
浏览 200回答 2
2回答

宝慕林4294392

当您要在一个线程中处理一个类中的多个变量时,是否应该为要锁定在该类中的每个变量都拥有一个“锁定对象”?有两个规则:要“细粒度”。拥有尽可能多的锁,每个变量一个。每次使用它时,都应在其锁下访问变量。锁定尽可能少的代码以确保可伸缩性。如果忘记锁定变量,则会导致争用情况;如果锁定顺序错误,则会导致死锁,因此请确保其完美无缺。要“粗粒度”。仅拥有一个锁,然后将所有关键部分放在该锁下。拥有多个锁可以减少争用,但会增加死锁和其他错误的可能性,因此锁应尽可能少,每个锁中要包含尽可能多的代码。当然,这也增加了死锁的风险,因为现在锁中有很多代码可以进行倒置,并且降低了可伸缩性。毫无疑问,标准建议是完全矛盾的。那是因为锁很糟糕。我的建议:如果您不跨线程共享变量,则根本不需要任何锁。这也是处理线程安全自定义类型的有效方法吗?到目前为止,代码看起来还算合理,但是如果您打算延迟加载某些逻辑,则不要编写自己的线程逻辑。只需使用Lazy<T>并使其起作用即可。它是由专家撰写的。始终使用专家提供的最高级工具。滚动自己的线程原语是灾难的根源。无论您采取什么措施,都不要采纳另一个答案中的建议,即您必须使用双重检查锁定。有没有什么情况下,你必须使用双重检查锁定。单次检查锁定更安全,更容易且更可能正确。仅在以下情况下使用双重检查锁定:(1)您有大量的经验证据表明争用是可衡量的,影响用户的性能问题的原因,该问题将通过低锁定得到解决,并且(2)您可以解释C#内存模型使双重检查锁定变得安全。如果您不能执行(1),那么您就没有理由进行双重检查锁定;如果您不能执行(2),则不能放心任何安全性。

慕的地10843

您需要使用双重检查的锁定模式。初始化someClass之后,无需获取someClassLock锁,将其锁定在那只会导致不必要的争用。if (someClass == null){&nbsp; &nbsp; lock(someClassLock)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (someClass == null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; someClass = new SomeClass();&nbsp; &nbsp; }}您需要内部if块,因为并发线程可能在第一次空检查之后但在获取锁之前创建了someClass。当然,您还需要确保以某种本身是线程安全的方式编写SomeClass,但这将安全地确保仅创建someClass的一个实例。另一种方法是使用Lazy<T>合适的LazyThreadSafetyMode。
随时随地看视频慕课网APP
我要回答