这段代码是正确的还是有可能出现一些随机线程死锁等?
使用静态属性和锁定在一起是个好主意吗?还是静态属性是线程安全的?
Private Shared _CompiledRegExes As List(Of Regex)
Private Shared Regexes() As String = {"test1.Regex", "test2.Regex"}
Private Shared RegExSetupLock As New Object
Private Shared ReadOnly Property CompiledRegExes() As List(Of Regex)
Get
If _CompiledRegExes Is Nothing Then
SyncLock RegExSetupLock
If _CompiledRegExes Is Nothing Then
_CompiledRegExes = New List(Of Regex)(Regexes.Length - 1)
For Each exp As String In Parser.Regexes
_CompiledRegExes.Add(New Regex(exp, RegexOptions.Compiled Or RegexOptions.CultureInvariant Or RegexOptions.IgnoreCase))
Next
End If
End SyncLock
End If
Return _CompiledRegExes
End Get
End Property
如果不明显,代码正在编译正则表达式并存储在 List(Of Regex) 中,以便它们可以运行得更快。它是共享的,因此类的每个实例都可以从中受益。
最佳答案
您的代码不是线程安全的,因为您使用的是双重检查锁定而不会使字段变得不稳定。不幸的是,VB.NET 没有 volatile 修饰符,因此您无法应用正常的修复程序。改为每次都获取锁,或者在类型初始化时使用静态初始化来初始化_CompiledRegExes。
有关单例的一般性讨论,请参阅 my singleton page - 我知道这不是一个单例,但很接近。该页面提供了 C# 代码,但应该很容易理解。
此外,我通常建议将锁变量设为只读。你真的不想改变值(value):)
笼统:
编辑:您不需要将类型设为单例。只需编写函数来初始化列表并返回它,然后在变量的初始化程序中使用该函数:
' This has to be declared *before* _CompiledRegExes '
' as the initializer will execute in textual order '
' Alternatively, just create the array inside BuildRegExes '
' and don't have it as a field at all. Unless you need the array '
' elsewhere, that would be a better idea. '
Private Shared ReadOnly Regexes() As String = {"test1.Regex", "test2.Regex"}
Private Shared ReadOnly _CompiledRegExes As List(Of Regex) = BuildRegExes()
Private Shared ReadOnly Property CompiledRegExes() As List(Of Regex)
Get
Return _CompiledRegExes
End Get
End Property
Private Shared Function BuildRegExes() As List(Of Regex)
Dim list = New List(Of Regex)(Regexes.Length - 1)
For Each exp As String In Regexes
_CompiledRegExes.Add(New Regex(exp, RegexOptions.Compiled Or RegexOptions.CultureInvariant Or RegexOptions.IgnoreCase))
Next
Return list
End Function
关于.net - 静态属性和锁使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/691356/