这段代码是正确的还是有任何随机线程死锁的可能性等?
使用静态属性并锁定在一起是一个好主意吗?或者是静态属性线程安全吗?
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)中,那么它们可以更快地运行.并且它是共享的,因此每个类的实例都可以从中获益.
您的代码不是线程安全的,因为您使用双重检查锁定而不使字段变为volatile.不幸的是VB.NET没有volatile修饰符,所以你不能应用正常的修复.只需每次获取锁,或者在初始化类型时使用静态初始化初始化_CompiledRegExes.
请参阅我的单页为这至于单身了一般性讨论-我知道这是不是相当一个单,但已经很接近了.该页面提供了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