Skip to main content
added tag and formatting
Source Link
Malachi
  • 29.1k
  • 11
  • 87
  • 188

If iI am right, the .NET Dictionary is thread-safe, as long as it is used only in read access, thus not requiring locks in reading methods. The dictionary will not be changed after being assigned to the _progObjects_progObjects variable (do I need to make it volatile?). But time consuming volatile (alternatively Interlocked) access on the _areProgObjectsInitialized_areProgObjectsInitialized variable seems to be neccessarynecessary, to make first accesses (with initialization) thread-safe.

If i am right, the .NET Dictionary is thread-safe, as long as it is used only in read access, thus not requiring locks in reading methods. The dictionary will not be changed after being assigned to the _progObjects variable (do I need to make it volatile?). But time consuming volatile (alternatively Interlocked) access on the _areProgObjectsInitialized variable seems to be neccessary, to make first accesses (with initialization) thread-safe.

If I am right, the .NET Dictionary is thread-safe, as long as it is used only in read access, thus not requiring locks in reading methods. The dictionary will not be changed after being assigned to the _progObjects variable (do I need to make it volatile?). But time consuming volatile (alternatively Interlocked) access on the _areProgObjectsInitialized variable seems to be necessary, to make first accesses (with initialization) thread-safe.

Tweeted twitter.com/#!/StackCodeReview/status/205618015755182080
Post Migrated Here from stackoverflow.com (revisions)
Source Link
Erik Hart
  • 311
  • 1
  • 5
  • 11

Thread-safe object cache, for read, high performance in .NET

I want to realize an object cache which holds objects loaded from database, file or other slow access source, to make them available quickly with high performance. There will be a lot of accesses to get these objects from the dictionary!

It's not supposed to be Singleton/Static; multiple different object holders are possible, with multiple threads running on each.

Access is usually read-only, the objects themselves (in the dictionary) shall not be changed after being created.

For some special Admin functions, a Reload method exists, where thread safety can be ignored (not to be used by the main, multi-threaded program).

If i am right, the .NET Dictionary is thread-safe, as long as it is used only in read access, thus not requiring locks in reading methods. The dictionary will not be changed after being assigned to the _progObjects variable (do I need to make it volatile?). But time consuming volatile (alternatively Interlocked) access on the _areProgObjectsInitialized variable seems to be neccessary, to make first accesses (with initialization) thread-safe.

Is the following a good and performant solution, can it still be improved, or are there safety risks?

/// <summary>
/// Not Singleton, but each instance multi-threaded!
/// Holds objects loaded from an external source (database, file, whatever...)
/// </summary>
public class ProgObjectsThreadSafeRead : IProgObjectsThreadSafeRead
{
    private IDictionary<ObjectKey, object> _progObjects = null;
    private object _progObjectsSyncObj = new object();
    private volatile bool _areProgObjectsInitialized = false;

    private void InitializeProgObjectsIfNeeded()
    {
        if (!_areProgObjectsInitialized)
        {
            lock(_progObjectsSyncObj)
            {
                if (!_areProgObjectsInitialized)
                {
                    IDictionary<ObjectKey, object> localProgObj = LoadProgObjects();
                    // do something more
                    _progObjects = localProgObj;
                    _areProgObjectsInitialized = true;
                }
            }
        }
    }

    public object GetProgObject(ObjectKey key)
    {
        InitializeProgObjectsIfNeeded();
        return _progObjects[key];
    }

    /// <summary>
    /// Not thread safe, don't use in multi-thread environments!
    /// Specific editing tools only! Not in interface.
    /// </summary>
    public void ReloadProgObjects()
    {
        lock (_progObjectsSyncObj)
        {
            _areProgObjectsInitialized = false;
            InitializeProgObjectsIfNeeded();
        }
    }

    
    // others removed
}