3
\$\begingroup\$

Thanks to ASP.NET Core dependency injection, there's no need to follow the Singleton pattern; any class will do.

What I want to do is to have a class that will store a value that'll be used by another methods inside the app. A specific class is in charge of updating this value. What I'm concerned is the problem of a thread reading the value while the specific class updates it, given that I haven't done enough concurrency to feel confident.

So I came up with this. Is it correct for what I want it to do?

public class DynamicValueStore
{
    private readonly object _lock_obj;
    
    private string _value;

    public string Value
    {
        get 
        {
            lock (_lock_obj)
            {
                return _value;  
            }
        }
    }

    public DynamicValueStore()
    {
        _lock_obj = new object();
        _value = string.Empty;
    }

    public void UpdateValue(string value)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            throw new ArgumentNullException(nameof(value));
        }
        lock (_lock_obj)
        {
            _value = value;
        }
    }
}
```
\$\endgroup\$
1

2 Answers 2

6
\$\begingroup\$

That will lock it down for sure. If you know you will have more reads then writes, which is common, you should look at the ReaderWriterLockSlim class. What you have will only allow one read and one write and they all queue up in line waiting their turn. The ReaderWriterLockSlim class will still only allow one write at a time but allow multiple reads at a time.

\$\endgroup\$
2
  • \$\begingroup\$ So the idea is to replace the lock with a ReaderWriterLockSlim object and use that to lock my reads and writes? Because yes, I'll have a lot more reads than writes. \$\endgroup\$
    – Léster
    Commented Jan 14, 2021 at 16:34
  • \$\begingroup\$ Yes readerlockslim would replace the lock. If you look at document you can see how to use it. There are lots of examples of its use online \$\endgroup\$ Commented Jan 14, 2021 at 16:43
2
\$\begingroup\$

I followed CharlesNRice's suggestion and here's a version of the code that behaves better when there are more reads than writes:

public class DynamicValueStore : IDisposable
{
    private readonly ReaderWriterLockSlim _lock_obj;
    
    private string _value;
    private bool _already_disposed;

    public string Authvalue
    {
        get 
        {
            _lock_obj.EnterReadLock();
            try
            {
                return _value;
            }
            finally
            {
                _lock_obj.ExitReadLock();
            }
        }
    }

    public DynamicValueStore()
    {
        _lock_obj = new ReaderWriterLockSlim();
        _value = string.Empty;
    }

    public void UpdateValue(string value)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            throw new ArgumentNullException(nameof(value));
        }
        _lock_obj.EnterWriteLock();
        try
        {
            _value = value;
        }
        finally
        {
            _lock_obj.ExitWriteLock();
        }
    }

    protected virtual void Dispose(bool disposeManagedObjects)
    {
        if (!_already_disposed)
        {
            if (disposeManagedObjects)
            {
                _lock_obj.Dispose();
            }
            _already_disposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(disposeManagedObjects: true);
        GC.SuppressFinalize(this);
    }
}
```
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.