.net - 静态属性和锁使用

标签 .net vb.net performance multithreading locking

这段代码是正确的还是有可能出现一些随机线程死锁等?

使用静态属性和锁定在一起是个好主意吗?还是静态属性是线程安全的?

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/

    相关文章:

    c# - 自 1.2.11 版本以来,log4net.Appender.AsyncAppender 类是否已删除?

    .net - 是否有用于 .NET 的库可以执行括号或表达式缩减和优化?

    c# - 如何在类型变量中创建任何类型的字典?

    c# - Windows 窗体中的异步

    .net - 使用设计器支持将表单作为属性添加到用户控件

    vb.net - 修改 Devexpress 中主从网格中的列标题名称

    c - 赋值与增量操作

    mysql - 分区和更新

    asp.net - 如何在运行时添加数据时隐藏gridview的一列?

    .net - WPF控制性能