多线程 - 初始化共享数据的争用条件



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

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

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

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

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

看起来微不足道,但不知何故想不出任何可以解决这个问题的多线程功能。

我的代码如下所示:

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

您可以尝试以下逻辑1) 线程 1 来了,发现缓存中不存在该对象2) 将等待命令对象放在此会话 ID 的缓存中。此对象告诉任何其他线程等待,直到另行通知。3) Thread1 从数据库中获取数据并将其放回缓存中。4) Thread1 通知其他线程它们可以继续,因为数据现在可用。

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

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
    }
}

最新更新