我正在使用静态成员来缓存一些数据而我相信我在首次填充缓存数据时遇到某种并发问题。这个问题是零星的,似乎跟随应用程序池的回收(虽然通常不会出现问题)。
最初我的_CachedData成员为null。当调用FindAll()方法时,当_CachedData不为null时,它将使用缓存的数据,否则它将从数据库加载数据。只要对数据执行插入,更新或删除,_CachedData成员就会设置为null,但在应用程序池回收后首次加载应用程序时,这种情况永远不会发生。
当我将一个TestClass对象添加到_CachedData的结果时,我得到的错误是一个对象引用错误。我只是看不出这是怎么可能的,因为我在输入for each循环之前对_CachedData执行了空检查。
Public Class TestClass
Private Shared _CachedData As Collection(Of TestClass) = Nothing
Sub New()
End Sub
Public Shared Function FindAll() As Collection(Of Content.TestClass)
Dim result As New Collection(Of TestClass)()
If _CachedData IsNot Nothing Then
' retrieve from cache
For Each tc As TestClass In _CachedData
result.Add(CType(tc.MemberwiseClone(), TestClass))
Next
Else
result = GetFromDatabase()
' save to cache
_CachedData = New Collection(Of TestClass)()
SyncLock _CachedData
' make sure the cache wasn't populated while we were aquiring the lock
If _CachedData.Count = 0 Then
For Each tc As TestClass In result
_CachedData.Add(CType(tc.MemberwiseClone(), TestClass))
Next
End If
End SyncLock
End If
Return result
End Function
FAF
答案 0 :(得分:0)
对于初学者,你实际上不应该锁定对象本身,因为你将对该对象进行更改。您应该更新您的代码:
Private Shared _CachedData As Collection(Of TestClass) = Nothing
Private Shared ReadOnly _CachedDataLock As Object = New Object()
Public Shared Function FindAll() As Collection(Of Content.TestClass)
Dim result As New Collection(Of TestClass)()
If _CachedData IsNot Nothing Then
' retrieve from cache, using a local instance to avoid race-conditions
Dim localCachedData As Collection(Of TestClass) = _CachedData
For Each tc As TestClass In localCachedData
result.Add(CType(tc.MemberwiseClone(), TestClass))
Next
Else
result = GetFromDatabase()
' save to cache
SyncLock _CachedDataLock
' make sure the cache wasn't populated while we were aquiring the lock
If _CachedData Is Nothing Then
_CachedData = New Collection(Of TestClass)()
For Each tc As TestClass In result
_CachedData.Add(CType(tc.MemberwiseClone(), TestClass))
Next
End If
End SyncLock
End If
Return result
End Function