【问题标题】:Thread synchronisation among multithreads accessing singleton object访问单例对象的多线程之间的线程同步
【发布时间】:2019-10-18 11:40:49
【问题描述】:

我想看看下面的代码在健壮代码和干净代码方面是否有更好的方法。

// Encryption is singleton via IoC
public class Encryption{

        private volatile ConcurrentDictionary<string, string> _blobs = new ConcurrentDictionary<string, string>();
        private object _encryptedDataLock = new object();
        public string CreateEncryptedData(string key)
        {
            string encryptedData = string.Empty;

            if (_cloudBlobs.ContainsKey(key))
                encryptedData = _blobs[key];

            lock (_encryptedDataLock)
            {

                if (!_cloudBlobs.ContainsKey(key))
                {
                    encryptedData = CalulateEncryptedData();
                    _blobs.TryAdd(key, encryptedData);

                    return encryptedData;

                }
            }

            return encryptedData;
        }
}

更新

我正在寻找不使用锁定对象、双重检查、易失性、尽可能少的代码的解决方案。

【问题讨论】:

  • _blobs 不需要是易失的,因为它从未被写入。你也可以readonly
  • 但它有_blobs.TryAdd
  • 没关系。这不是 volatile 的工作原理
  • 好的,您能否详细说明或提供链接以便我完全理解?提前致谢。
  • 阅读:albahari.com/threading。您永远不会分配给 _blobs 字段。

标签: c# asp.net .net asp.net-core .net-core


【解决方案1】:

如果两个线程同时使用相同的key调用CreateEncryptedData,可能会出现三种结果:

  1. CalulateEncryptedData() 只被调用一次,两个线程都得到结果,结果存储在 _blobs 中。
  2. CalulateEncryptedData() 被调用两次,但其中一次调用的结果被丢弃。两个线程得到相同的结果,并且该结果也存储在_blobs
  3. CalulateEncryptedData() 被调用两次,两个线程得到不同的结果。其中一个结果存储在_blobs 中。显然这是不可取的。

如果你需要case 1,那么你需要一个单独的锁对象,但是你可以这样写:

public string CreateEncryptedData(string key)
{
    if (_blobs.TryGetValue(key, out var value))
        return value;

    lock (_encryptedDataLock)
    {
        return _blobs.GetOrAdd(key, x => CalulateEncryptedData());
    }
}

如果情况2没问题,你可以进一步简化为:

public string CreateEncryptedData(string key)
{
    return _blobs.GetOrAdd(key, x => CalulateEncryptedData());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多