双重检查锁定,基本问题 [英] double check lock, basic question

查看:48
本文介绍了双重检查锁定,基本问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我从http://bryblog.com/broken-double-check-lock获得的片段



忘记其他问题,如使TheLazyOne易变等据我了解,目的是让任何希望访问内部关键部分的线程能够阻止,如果另一个内部存在则阻塞。似乎会有一种情况,当一个线程跳过并再试一次。假设我有两个线程,A和B. A在csx内部,它完成并且TheLazyOne仍然存在。 B试图进入并且外部if计算为false。

是否暗示在线程退出csx之前对TheLazyOne有空赋值?



另外,TheLazyOne可以只是一个布尔值吗?



最好。



< pre lang =cs> object SyncRoot = new object ();
object TheLazyOne = null ;


if (TheLazyOne == null
{
lock (SyncRoot)
{
if (TheLazyOne == null
TheLazyOne = new object ();
}
}





所以,即使有空分配,在csx之前的任何一点都可以退出,试图进入的线程不会阻止。相反,它只需要再试一次。我相信所需的行为是阻止它。

解决方案

只有第一次调用延迟实例化时才需要此语法。该实例最后仍应返回:





 私有 静态 对象 SyncRoot =  new   object (); 
私有 静态 对象 TheLazyOne = null ;

public static object 实例{
获取 {
// 第一个调用者将看到TheLazyOne为null
如果(TheLazyOne == null
{
// 在第一个调用者创建实例之前,第二个偷偷溜进它后面
lock (SyncRoot)
{
// 第一个调用者可以创建新实例,因为它仍为空
if (TheLazyOne == null
TheLazyOne = new object ();
// 第二个调用者等待锁定直到第一个存在
< span class =code-comment> // 第三个来电者现在可以跳到最后
}
// 第一个调用者退出并允许第二个调用者尝试。 TheLazyOne不再为null,因此它会跳过实例化
}
// 第一个&安培;第二个呼叫者(以及任何未来的呼叫者)都在这里返回单身
return TheLazyOne;
}
}







我希望您的解释就是您所期待的对于。如果我误解,请告诉我。



(PS:我认为.Net5有一个等价物(Citation needed ^!):



  private   static  Lazy< object> ; TheLazyOne =  new  Lazy< object>(); 
public static object 实例{
get {
返回 TheLazyOne.Value;
}
} < / 对象 > < / object >


1.如文章所述,双重检查的目标是避免使用locki产生的性能影响NG。例如,在简单检查的情况下,可能是其他线程已经放置外观的情况。



2.The TheLazyOne 也可以是bool,在这种情况下你应该检查是否为true。但请注意将 TheLazyOne 声明为 volatile


首先关闭,谢谢你有时间试图理解我的问题。



i相信你们(至少是安迪)处于用于单身人士目的的关键部分的心态中。



我关心的是更常见的关键部分用法。如果第二个线程B试图进入csx(第一个空检查),而较早的线程A在将TheLazyOne重新分配回null之前的某个点内,则第一个空检查将为false,因此它不会阻塞。它将跳过,并且必须再试一次。



如果双重检查锁是'故意',单身人士懒惰地实例化一个监控类来进入csx ,我认为这回答了我的问题。但如果它是用于一般线程同步来访问csx,那么我认为我的问题是有道理的(至少对我来说=))。


Below is a snippet I got from http://bryblog.com/broken-double-check-lock

Forget the other issues like making TheLazyOne volatile etc. As I understand, the intention is for any thread wanting to access the critical section inside to be able to, blocking if another is inside. It seems there will be a situation, when a thread would skip and try again. Say I have two threads, A and B. A is inside the csx, it finishes and TheLazyOne is still alive. B tries to get in and the outer if evaluates to false.
Is it implied that there is a null assignment to TheLazyOne just before a thread exits the csx?

Also, can TheLazyOne just be a boolean?

Best.

object SyncRoot = new object();
object TheLazyOne = null;


if (TheLazyOne == null)
{
    lock (SyncRoot)
    {
        if (TheLazyOne == null)
            TheLazyOne = new object();
    }
}



So, even if there was null assignment, at any point within the csx before it exits, a thread trying to get in won't block. Instead it will just have to try again. I believe the desired behaviour is for it to block.

解决方案

This syntax is only required for a first call of a lazy instantiation. The instance should still be returned at the end:


private static object SyncRoot = new object();
private static object TheLazyOne = null;
 
public static object Instance{
  get{ 
    //The first caller will see TheLazyOne as null
    if (TheLazyOne == null)
    {
        //Before the first caller gets to create the instance, a second one snuck in behind it
        lock (SyncRoot)
        {
            //The first caller can create the new instance as it is still null
            if (TheLazyOne == null)
                TheLazyOne = new object();
            //The second caller waits at the lock until the first exists
            //A third caller will now be able to skip to the end
        }
        //The first caller exits and allows the second to try.  TheLazyOne is no longer null so it skips instantiation
    }
    //The first & second callers (as well as any future callers) all end up here to return the singleton
    return TheLazyOne;
  }
}




I hope that explanation is what you were looking for. Please let me know if I mis-understood.

(PS: I think .Net5 has an equivalent (Citation needed^!):

private static Lazy<object> TheLazyOne = new Lazy<object>();
public static object Instance{
  get{
    return TheLazyOne.Value;
  }
} </object></object>


1.Like the article said, the goal for double checking is to avoid the performance impact generated by using locking. For example in the case of simple check, could be the situation when the look is already put by other thread.

2.The TheLazyOne can be also a bool, an in this case you should check for true. But be aware to declare TheLazyOne as volatile!


first off, thank you for your time trying to understand my question.

i believe you guys (at least Andy) is in the mindset of the critical section being used for the purpose of a singleton.

my concern is of a more general critical section usage. if a second thread B tries to get inside the csx (first null check), while an earlier thread A is inside at a point before the reassignment of TheLazyOne back to null, the first null check will be false and therefore it wouldn't block. it will skip and would have to try again.

if double-check lock is 'purpose-made' for singleton to lazily instantiate a monitor class to get inside the csx, i think that answers my question. but if it is meant to be used for a general thread sync to access a csx, then i think my question makes sense (to me at least =)).


这篇关于双重检查锁定,基本问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆