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
,则网络结果将是附加 FredJoe
或 JoeFred
,而不是类似 FrJoeed
的内容),上面的代码将使每个线程读取 _thing
,生成一个附加文本的版本,然后尝试更新 _thing
。如果其他线程同时更新了 _thing
,则放弃最后构造的字符串,根据更新的 _thing
创建一个新字符串,然后重试。
请注意,虽然这种方法不一定比锁定方法更快,但它确实提供了一个优点:如果获取锁的线程陷入无限循环或以其他方式被拦截,则所有线程将永远被阻止访问该锁。锁定资源。相比之下,如果上面的 WithSomeChanges()
方法陷入无限循环,_thing
的其他用户不会受到影响。
关于vb.net - 这个简单的 VB.Net 类线程安全吗?如果没有,我该如何改进?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14280672/