vb.net - 这个简单的 VB.Net 类线程安全吗?如果没有,我该如何改进?

标签 vb.net thread-safety

Option Strict On

Public Class UtilityClass
  Private Shared _MyVar As String

  Public Shared ReadOnly Property MyVar() As String
    Get
      If String.IsNullOrEmpty(_MyVar) Then
        _MyVar = System.Guid.NewGuid.ToString()
      End If
      Return _MyVar
    End Get
  End Property

  Public Shared Sub SaveValue(ByVal newValue As String)
    _MyVar = newValue
  End Sub

End Class

最佳答案

虽然锁定是增加线程安全性的一种很好的通用方法,但在许多涉及一次写入准不变性的场景中,一旦写入非空值,字段就应该变得不可变,线程。 Interlocked.CompareExchange 可能会更好。本质上,该方法读取一个字段,并且在其他任何人可以触及它之前,当且仅当该字段与提供的“比较”值匹配时写入一个新值;它返回在任何情况下读取的值。如果两个线程同时尝试进行CompareExchange,并且两个线程都将字段的当前值指定为“比较”值,则其中一个操作将更新该值,而另一个则不会,并且每个操作都会“知道” “是否成功。

CompareExchange 有两种主要使用模式。第一个对于生成可变单例对象最有用,其中每个人都看到相同的实例很重要。

If _thing is Nothing then
    Dim NewThing as New Thingie() ' Or construct it somehow
    Threading.Interlocked.CompareExchange(_thing, NewThing, Nothing)
End If

这种模式可能就是您所追求的。请注意,如果一个线程在另一个线程执行上述代码的时间和执行 CompareExchange 的时间之间输入上述代码,则两个线程最终都可能创建一个新的 Thingie。如果发生这种情况,无论哪个线程首先到达 CompareExchange,都会将其新实例存储在 _thing 中,而另一个线程将放弃其实例。在这种情况下,线程并不关心它们是赢还是输;它们只关心它们是赢还是输。 _thing 中将有一个新实例,并且所有线程都会在那里看到相同的实例。另请注意,由于在第一次读取之前不存在内存屏障,因此理论上,过去某个时间检查过 _thing 值的线程可能会继续将其视为 Nothing,直到某些原因导致其更新它的缓存,但如果发生这种情况,唯一的后果将是创建一个无用的 Thingie 新实例,当 Interlocked.CompareExchange 发现 时,该实例将被丢弃_thing 已被写入。

另一种主要使用模式对于更新对不可变对象(immutable对象)的引用很有用,或者(稍加修改)更新某些值类型(例如 Integer 或 Long)。

Dim NewThing, WasThing As Thingie
Do
    WasThing = _thing
    NewThing = WasThing.WithSomeChange();
Loop While Threading.Interlocked.CompareExchange(_thing, NewThing, WasThing) IsNot WasThing

在这种情况下,假设存在某种方法,通过给定 Thingie 的引用,可以廉价地生成一个与所需方式不同的新实例,则可以以线程安全的方式对 _thing 执行任何此类操作。例如,给定一个String,可以轻松地生成一个附加了一些字符的新String。如果希望以一种线程安全的方式将一些文本附加到字符串中(例如,如果一个线程尝试添加 Fred 而另一个线程尝试添加 Joe,则网络结果将是附加 FredJoeJoeFred,而不是类似 FrJoeed 的内容),上面的代码将使每个线程读取 _thing ,生成一个附加文本的版本,然后尝试更新 _thing。如果其他线程同时更新了 _thing,则放弃最后构造的字符串,根据更新的 _thing 创建一个新字符串,然后重试。

请注意,虽然这种方法不一定比锁定方法更快,但它确实提供了一个优点:如果获取锁的线程陷入无限循环或以其他方式被拦截,则所有线程将永远被阻止访问该锁。锁定资源。相比之下,如果上面的 WithSomeChanges() 方法陷入无限循环,_thing 的其他用户不会受到影响。

关于vb.net - 这个简单的 VB.Net 类线程安全吗?如果没有,我该如何改进?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14280672/

相关文章:

vb.net - 在 .NET 中解码基本授权的最简单方法

mysql - 如何将列表框的项目存储到 MySQL 表的不同行中

java - 线程安全的 ArrayList 合并 : will this work?

c - 共享库局部变量线程安全吗?

java - 销毁正在运行的线程并在新变量中重新初始化

java - 使用双重检查惯用语重置延迟加载的字段

vb.net - 控制面板在笔记本电脑屏幕上时控制输出到电视显示器?

vb.net - 如何让按钮背景透明?

.net - Byte = 8bits,但为什么BitConverter不这么认为

python - Django 中的线程安全存储