Click here to Skip to main content
15,896,453 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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.

C#
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.
Posted
Updated 1-Apr-15 23:58pm
v3

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


C#
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^!):

C#
private static Lazy<object> TheLazyOne = new Lazy<object>();
public static object Instance{
  get{
    return TheLazyOne.Value;
  }
} </object></object>
 
Share this answer
 
v3
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!
 
Share this answer
 
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 =)).
 
Share this answer
 
Comments
Afzaal Ahmad Zeeshan 2-Apr-15 7:13am    
Please comment this to their post. Do not post it as a new question.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900