我正在尝试实现以下方案,但无法提出解决方案。
在我的 Web 服务中,我根据会话 ID 缓存对象(包含静态数据)。收到请求后,它会检查缓存是否包含会话 ID 的任何键。
- 如果不可用,它将从数据库加载它并将其存储在缓存中。
- 如果可用,它将使用该缓存并继续进一步处理。
启用多线程后,当多个请求(具有相同的会话 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
}
}