这是情景:
主题A要求使用法语的所有书籍
主题B要求使用阿拉伯语的所有书籍
如果线程A位于锁定区域,则线程B将在锁定区域外等待线程A完成。
因为代码中只有一个“地方”,主题B可以获取他的数据。
我想基于缓存中的Key进行锁定,这意味着:
if(Cache["BooksInFrench"] == null)
{
lock("BooksInFrench")
{
if(Cache["BooksInFrench"] == null)
{
object d = GetFromDB();
cache["BooksInFrench"] = d;
}
}
同样适用于BooksInArabic等.... 所以这样,如果我有200个连接到我的网站 其中10人要求BookInFrench 其余的请求(BooksInArabic,BooksInHebrew .......)可以运行并获取他们的数据因为他们的请求不在锁中 区域。
我当前的代码如下所示: http://pastebin.com/LFhxgHDM
我认为双重锁定不是很好...... 你看到其他任何解决方案/改进吗?
答案 0 :(得分:0)
它可能只是在您的示例伪代码中,但locking on objects is recommended over strings(因为较低级别的优化,如不可变共享字符串,规范版本等等 - 请参阅Locking by string. Is this safe/sane?)。
对于单个已知的lock
:
// In your class
private static readonly object BooksInFrenchLock= new object();
private const string BookInFrenchCacheKey = "BooksInFrench";
// In your cache block
if(Cache[BookInFrenchCacheKey] == null)
{
lock(BooksInFrenchLock)
{
if(Cache[BookInFrenchCacheKey] == null)
{
object d = GetFromDB();
Cache[BookInFrenchCacheKey] = d;
}
}
为了从数据库中锁定多个对象,您可以使用ConcurrentDictionary
而不是哈希表(如your pastebin code中所示) - 它将为您节省一个额外的“级别”锁定。神奇的事情发生在BookLocks.GetOrAdd(bookLanguage, s => new object())
。
// In your class
private static readonly ConcurrentDictionary<string, object> BookLocks =
new ConcurrentDictionary<string, object>();
// In your cache block
string bookLanguage = formatAndCleanBookLanguageArgument();
if(Cache[bookLanguage] == null)
{
object lockObject = BookLocks.GetOrAdd(bookLanguage, s => new object());
lock(lockObject)
{
if(Cache[bookLanguage] == null)
{
object d = GetFromDB();
Cache[bookLanguage] = d;
}
}