Again double checked lock and C #

Recently, I was refactoring some of my C # code, and I found several double-validation checks. I did not know that it was a bad practice, and I really want to get rid of it.

The problem is that I have a class that needs to be lazily initialized and often accessible by multiple threads. I also do not want to move initialization to a static initializer, because I plan to use a weak reference to keep the initialized object in memory too long. However, if necessary, I want to “animate” the object, ensuring that this happens in a thread-safe manner.

I was wondering if you use ReaderWriterLockSlim in C # and enter UpgradeableReadLock before the first check, and then enter a write lock for initialization if necessary, this would be an acceptable solution. Here is what I mean:

public class LazyInitialized
{
    private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();

    private volatile WeakReference _valueReference = new WeakReference(null);
    public MyType Value
    {
        get
        {
            MyType value = _valueReference.Target as MyType;
            _lock.EnterUpgradeableReadLock();
            try
            {
                if (!_valueReference.IsAlive) // needs initializing
                {
                    _lock.EnterWriteLock();
                    try
                    {
                        if (!_valueReference.IsAlive) // check again
                        {
                            // prevent reading the old weak reference
                            Thread.MemoryBarrier(); 
                            _valueReference = new WeakReference(value = InitializeMyType());
                        }
                    }
                    finally
                    {
                        _lock.ExitWriteLock();
                    }
                }
            }
            finally
            {
                _lock.ExitUpgradeableReadLock();
            }
            return value;
        }       
    }

    private MyType InitializeMyType()
    {
        // code not shown    
    }
}

, , . , , , , , , . , , , .

, , , _valueReference . .

+5
2

, @Mannimarco : , , ReaderWriterLockSlim Monitor.Enter/Monitor.Leave. .

, :

private WeakReference _valueReference = new WeakReference(null);
private object _locker = new object();

public MyType Value
{    
  get
  {    
    lock(_locker)  // also provides the barriers
    {
        value = _valueReference.Target;

        if (!_valueReference.IsAlive)
        {
            _valueReference = new WeakReference(value = InitializeMyType());
        }
        return value; 
    }
  }    
}
+2

: UpgradeableReadLock. ReaderWriterLockSlim. , , , , () . , .

EDIT: , , Monitor Wait and Pulse. , "" "" , , . , PulseAll . ()

+2

All Articles