假设我有两个线程(Thread1、Thread2),这些线程几乎同时访问给定对象的缓存,如下面的代码所示:
Dim expensiveToGetData = Cache("ExpensiveDataKey")
If ExpensiveToGetData is nothing then
'because the cache has expired
ExpensiveToGetData = LoadExpensiveDataFromDataSource()
Cache("ExpensiveDataKey") = ExpensiveToGetData
end If
ProcessExpensiveData(ExpensiveToGetData)
两个线程是否都可以加载缓存,因为它们都从缓存中请求了空的/过期的数据?我在本地计算机上运行了一些测试,似乎缓存被加载了不止一次。这是正常模式吗?
最佳答案
是的,使用该代码,两个不同的请求肯定可能不会从缓存中获取任何内容,因此都会重新加载数据。如果你想避免这种情况,你需要同步获取数据的整个操作。
同步访问的一种方法是使用类似于以下的代码:
Dim expensiveToGetData = Cache("ExpensiveDataKey")
If ExpensiveToGetData is nothing then
SyncLock yourLockObject /* YourLockObject should be a Shared object. */
expensiveToGetData = Cache("ExpensiveDataKey")
If expensiveToGetData Is Nothing Then
ExpensiveToGetData = LoadExpensiveDataFromDataSource()
Cache("ExpensiveDataKey") = ExpensiveToGetData
End If
End SyncLock
end If
ProcessExpensiveData(ExpensiveToGetData)
在获取锁之前检查是否获取到数据的想法是为了避免在高负载环境下过度锁定。如果不存在,我们需要在锁内再次检查,因为在我们获取锁时另一个线程可能已经获取了数据。
关于asp.net - 高并发系统中的缓存访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4198998/