c# - 使用悲观锁定将项目添加到 Microsoft.ApplicationServer.Caching.DataCache?

标签 c# azure locking pessimistic-locking

我正在服务器端的 Web 服务器上开发一个缓存层,使用 Azure 共享缓存来减少对数据库的请求量,从而使内容运行得更快(希望如此)。我所困惑的是如何使整个努力线程安全。我似乎没有找到可靠且可用的方法来锁定数据缓存中的 key 。我缺少的是一种在 key 上存储任何内容之前预先锁定 key 的方法,这样我就可以添加一个值,而不会有另一个线程尝试同时执行相同操作的风险。

到目前为止,我一直在专门研究悲观锁定,因为这就是线程安全对我来说最有意义的方式,我想确保我正在处理的内容被锁定。

我明白,如果我要使用悲观锁定,我只负责使用与之相关的方法。混合东西会弄乱整个锁定机制(来源:http://go4answers.webhost4life.com/Example/datacacheput-unlocking-key-77158.aspx)。

So basicly I only have access to these methods:
value GetAndLock(key, out DataCacheLockHandle);
void PutAndUnlock(key, value, DataCacheLockHandle);
void Unlock(key, DataCacheLockHandle);

问题是,如果我尝试获取缓存中尚未存在的内容,“GetAndLock”会引发异常。同时,我向缓存添加内容的唯一方法是“PutAndUnlock”,除非我成功执行“GetAndUnlock”,否则无法使用该方法。

实际上,不可能向缓存中添加任何新内容,唯一能做的就是替换已经存在的内容(这将是空的)。

所以在我看来,在“GetAndLock”抛出无异常的情况下,我被迫使用乐观的“Put”。不过,根据我读到的内容,乐观的“Put”会破坏使用“GetAndLock”实现的任何现有锁定,因此这会破坏线程安全的整个尝试。

Example plan:
1. Try to GetAndLock
2. In case of nothing there exception: 
     - Put a dummy item on the key. 
     - GetAndLock again.
3. We have a lock, do computations, query database etc
4. PutAndUnlock the computed value


One of probably several ways it would screw up:
Thread1: Tries to GetAndLock, gets nothing there exception
Thread2: Tries to GetAndLock, gets nothing there exception
Thread1: Put a dummy item on the key
Thread1: GetAndLock again, lock achieved
Thread2: Put a dummy item on the key (destroying Thread1:s lock)
Thread2: GetAndLock again, lock achieved
Thread1: We think we have a lock, do computations, query database etc
Thread2: We have a lock, do computations, query database etc
Thread1: PutAndUnlock the computed value (will this throw an exception?)
Thread2: PutAndUnlock the computed value

基本上,两个线程可以同时向同一个键写入不同的内容,忽略它们都认为自己拥有的锁。

我唯一的结论是DataCache的悲观锁功能不完整并且完全无法使用。我错过了什么吗?有办法解决这个问题吗?

我所缺少的是一种在 key 上存储任何内容之前预先锁定 key 的方法。

最佳答案

乔纳森,

您是否考虑过将内容添加到缓存的逻辑(请原谅我的伪代码)?

public bool AddToCache(string key, object value) {

DataCache dc = _factory.GetDefaultCache();  
object currentVal = dc.Get(key);

if (currentVal == null) {
    dc.Put(key, value);
    currentVal = dc.GetAndLock(key);

    if (value == currentVal) {
        //handle this rare occurrence + unlock.
        return false;
    } else {
                   dc.Unlock(key);
            }
} else {
    currentVal = dc.GetAndLock(key);
    dc.PutAndUnlock (key, value);
}

return true;

}

关于c# - 使用悲观锁定将项目添加到 Microsoft.ApplicationServer.Caching.DataCache?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15364331/

相关文章:

C# String 处理非定界字符串列表

c# - 模型无效时不显示 MVC 客户端验证摘要

c# - WindowsInstaller msi数据库查询sql有什么限制

powershell - Azure CLI 能否获取租户中运行的所有资源的列表?

c# - 多线程场景调用Dictionary对象的set_item方法抛出NullReferenceException

c# - WebClient 无法使用正确的 Content-Type 集正确解码

sql - 将包含加密列的 Azure SQL Server 数据库从一个订阅复制到另一个订阅的最佳方法

azure - Azure 上的 Spark SSD

c++ - 使用WinDbg查找谁为本地进程持有SRW锁

database - spring hibernate 获取整个数据库的锁