此代码是否正确或是否有任何随机线程死锁等可能性?
使用静态属性并锁定在一起是否是一个好主意?或者是静态属性线程安全吗?
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)中,那么它们可以更快地运行。并且它是共享的,因此每个类的实例都可以从中获益。
答案 0 :(得分:8)
您的代码不是线程安全的,因为您使用的是双重检查锁定,而不会使字段变为volatile。不幸的是VB.NET没有volatile修饰符,所以你不能应用正常的修复。只需每次获取锁,或者在初始化类型时使用静态初始化来初始化_CompiledRegExes。
有关单身人士的详细讨论,请参阅my singleton page - 我知道这不是相当单身人士,但它很接近。该页面提供了C#代码,但它应该很容易理解。
此外,我通常建议将锁变量设置为只读。你真的不想改变价值:)
一般而言:
编辑:您不需要将类型设为单身。只需编写函数来初始化列表并将其返回,然后在初始化器中为变量使用该函数:
' 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
答案 1 :(得分:2)
(由jonskeet编辑)这篇文章只是为了让课程开始的格式化。如果在代码之前没有文本,不知道它为什么会失败。)
Class Better
Private Shared Regexes() As String = {"test1.Regex", "test2.Regex"}
Private Shared _CompiledRegExes As List(Of Regex) = BuildList(Regexes)
Private Shared Function BuildList(ByVal source() As String) As List(Of Regex)
Dim result = New List(Of Regex)(Regexes.Length - 1)
For Each exp As String In source
result.Add(New Regex(exp, RegexOptions.Compiled Or RegexOptions.CultureInvariant Or RegexOptions.IgnoreCase))
Next
Return result
End Function
Public Shared ReadOnly Property _CompiledRegExes1() As List(Of Regex)
Get
Return _CompiledRegExes
End Get
End Property
End Class
Class MoreBetter
Private Shared ReadOnly Regexes() As String
Private Shared ReadOnly _CompiledRegExes As List(Of Regex)
Shared Sub New()
Regexes = New String() {"test1.Regex", "test2.Regex"}
_CompiledRegExes = 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
End Sub
Public Shared ReadOnly Property _CompiledRegExes1() As List(Of Regex)
Get
Return _CompiledRegExes
End Get
End Property
End Class
编辑:我喜欢第二个的原因是它不容易出错。如果在“Private Shared Regexes()”
之前意外移动了“Private Shared _CompiledRegExes”,则第一个将无效答案 2 :(得分:1)
VB.Net有一个Static
关键字,可用于在成员或属性中声明变量。以这种方式声明的变量在调用方法时保持其状态,并保证是线程安全的(在幕后使用Monitor
类实现)。
答案 3 :(得分:1)
虽然我很少支持使用这种方法,但它是合法的。
Class UsingStatic
Private Shared Regexes() As String = {"test1.Regex", "test2.Regex"}
Public Shared ReadOnly Property CompiledRegExes() As List(Of Regex)
Get
Static _CompiledRegExes As List(Of Regex) = BuildList(Regexes) <--executes once
Return _CompiledRegExes <-- executes every time it is called
End Get
End Property
Private Shared Function BuildList(ByVal source() As String) As List(Of Regex)
Dim result = New List(Of Regex)(Regexes.Length - 1)
For Each exp As String In source
result.Add(New Regex(exp, RegexOptions.Compiled Or RegexOptions.CultureInvariant Or RegexOptions.IgnoreCase))
Next
Return result
End Function
End Class
请注意,您必须将_CompiledRegExes的构造函数放在同一行上。这个微小的变化会让你每次都得到一个新的物体。
Public Shared ReadOnly Property CompiledRegExes() As List(Of Regex)
Get
Static _CompiledRegExes As List(Of Regex) <--executes once
_CompiledRegExes = BuildList(Regexes) <-- executes every time it is called
Return _CompiledRegExes
End Get
End Property
答案 4 :(得分:0)
当您只有一个资源时,不会发生死锁。
关于静态属性,它们不是自动线程安全的。这是锁定私有静态字段的常用方法。
答案 5 :(得分:0)
“lockobject表达式应始终评估为专属于您的类的对象。您应该声明一个Private对象变量来保护属于当前实例的数据,或者声明一个Private Shared对象变量来保护所有公共数据实例“。