【问题标题】:Multithreading - Race condition to initialize shared data [duplicate]多线程-初始化共享数据的竞争条件[重复]
【发布时间】:2016-03-09 11:04:34
【问题描述】:

我正在尝试实施以下方案,但无法提出解决方案。

在我的网络服务中,我根据会话 ID 缓存了对象(包含静态数据)。收到请求后,它会检查缓存是否包含会话 ID 的任何键。

  1. 如果不可用,它将从数据库中加载并存储在缓存中。
  2. 如果可用,它会使用该缓存并继续进行进一步处理。

现在,在此服务中启用了多线程,并且当多个请求(具有相同会话 ID)被发送到服务时,它们都试图将数据加载到缓存中,因为它们最初都没有找到该键。

问题是:我想停止所有其他线程,直到第一个线程将静态数据加载到缓存中,一旦第一个线程完成将数据加载到缓存中,其他线程应该使用该缓存而不是再次尝试加载。

看起来微不足道,但不知何故无法想到任何可以解决此问题的多线程功能。

我的代码如下所示:

somemethod()
{
  if(cache.Contains(someKey)
  {
    // use cache and do further processing
  }
  else
  {
     cache.add(someKey)
  }
}

【问题讨论】:

    标签: c# multithreading wcf caching race-condition


    【解决方案1】:

    你可以试试下面的逻辑 1) Thread1 for 来了,发现缓存中不存在对象 2) 将此会话 ID 的等待命令对象放入缓存中。该对象告诉任何其他线程等待进一步通知。 3) Thread1 从 DB 中获取数据并将其放回缓存中。 4) Thread1 通知其他线程他们可以继续,因为数据现在可用。

    【讨论】:

      【解决方案2】:

      针对竞争条件的经典补救措施是互斥。锁定是提供这种能力的最简单的解决方案。

      public class Cache
      {
          private object _locker = new object();
          private SessionDataCollection _cache;
      
          public SessionData Get(SessionId id)
          {
              lock (_locker)
              {
                  if (!Contains(id))
                      Fetch(id);
      
                  return Retrieve(id);
              }
          }
      
          private bool Contains(SessionId id)
          {
              //check if present in _cache
          }
      
          private void Fetch(SessionId id)
          {
              //get from db and store in _cache
          }
      
          private SessionData Retrieve(SessionId id)
          {
              //retrvieve from _cache
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-11-08
        • 1970-01-01
        • 2012-04-29
        • 2016-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多