线程安全阅读Guid Twice
Thread safety reading Guid Twice
我正在读取一个 Guid 对象两次,一次在 if 语句中,一次在 if 语句块中。
在 C 中,我会在本地复制变量,以确保 if 语句中的读取操作不会读取不同的值(如果另一个线程在此期间更改了该值)。
我怀疑以下方法是否 a) 线程安全 b) 是否会给我相同的值:
public class MyClass {
private Guid MyProp {get;set;} = Guid.Empty; //May be changed at will
public OnRunLoop() //Gets called periodicaly on a thread
{
var ALocalCopyOfTheProp = MyProp; //Copy locally
if(ALocalCopyOfTheProp == AValueFromAnotherPlace) //Read 1
{
...
var AnotherReadOfTheVariable = ALocalCopyOfTheProp; //Read 2
}
...
}
C#.NET 本身没有从我的谷歌搜索中复制的功能,那么在这种情况下最佳实践是什么?
编辑:
- 请注意,在这种情况下,MyProp 不在我的手中。我不能使用锁,因为 属性 来自其他地方。 (抱歉没有说清楚)
- Guid 是结构而非引用类型
Guid is struct (value type) and its size is longer than atomically read values which are 32 or 64 bits depending on OS (What operations are atomic in C#?).
因此,如果可以从其他线程更改值,则您无法以线程安全的方式读取(或写入)Guid
值。访问 Guid
(读取和写入)的代码必须受到某种同步机制(即 lock
)的保护。
或者,如果您可以保证在对该字段的所有可能写入完成之前永远不会发生读取(实质上使字段不可变),您可以在没有锁的情况下读取它。如果同一字段有多个可能的写入器线程,则始终需要保护对 Guid
值的写入。
In C I would copy the variable locally, to make sure that the read operation inside the if-statement does not read a different value (if another thread changes this value in-between).
我注意到这种技术只是将一个问题——不一致的读取——换成了另一个问题——陈旧的读取。
这种技术在 C# 的多线程事件处理程序中很常见;你经常看到类似的东西:
var myEvent = this.MyEvent;
if (myEvent != null) myEvent(whatever);
虽然这确实解决了 this.MyEvent
在 if
和调用之间变化的竞争条件问题,但它没有解决更深层次的问题:您可以在一个线程上进行检查,在另一个线程上将事件处理程序设置为 null,现在事件处理程序永远不会被再次调用的假设是 false,因为将在另一个线程上调用过时值!
您不能简单地在本地复制东西并希望得到最好的结果。您必须证明 任何可能的重新排序 您在任意数量的线程 上的读取和写入会产生明智的计划。
The Guid object is a reference type
绝对不是。
C#.NET natively has no copy capabilities from my googling, so what is best-practice in a case such as this?
拿出一把锁。
I can not use a lock
那么你只需要在一个线程上调用你的属性。
我正在读取一个 Guid 对象两次,一次在 if 语句中,一次在 if 语句块中。
在 C 中,我会在本地复制变量,以确保 if 语句中的读取操作不会读取不同的值(如果另一个线程在此期间更改了该值)。
我怀疑以下方法是否 a) 线程安全 b) 是否会给我相同的值:
public class MyClass {
private Guid MyProp {get;set;} = Guid.Empty; //May be changed at will
public OnRunLoop() //Gets called periodicaly on a thread
{
var ALocalCopyOfTheProp = MyProp; //Copy locally
if(ALocalCopyOfTheProp == AValueFromAnotherPlace) //Read 1
{
...
var AnotherReadOfTheVariable = ALocalCopyOfTheProp; //Read 2
}
...
}
C#.NET 本身没有从我的谷歌搜索中复制的功能,那么在这种情况下最佳实践是什么?
编辑: - 请注意,在这种情况下,MyProp 不在我的手中。我不能使用锁,因为 属性 来自其他地方。 (抱歉没有说清楚) - Guid 是结构而非引用类型
Guid is struct (value type) and its size is longer than atomically read values which are 32 or 64 bits depending on OS (What operations are atomic in C#?).
因此,如果可以从其他线程更改值,则您无法以线程安全的方式读取(或写入)Guid
值。访问 Guid
(读取和写入)的代码必须受到某种同步机制(即 lock
)的保护。
或者,如果您可以保证在对该字段的所有可能写入完成之前永远不会发生读取(实质上使字段不可变),您可以在没有锁的情况下读取它。如果同一字段有多个可能的写入器线程,则始终需要保护对 Guid
值的写入。
In C I would copy the variable locally, to make sure that the read operation inside the if-statement does not read a different value (if another thread changes this value in-between).
我注意到这种技术只是将一个问题——不一致的读取——换成了另一个问题——陈旧的读取。
这种技术在 C# 的多线程事件处理程序中很常见;你经常看到类似的东西:
var myEvent = this.MyEvent;
if (myEvent != null) myEvent(whatever);
虽然这确实解决了 this.MyEvent
在 if
和调用之间变化的竞争条件问题,但它没有解决更深层次的问题:您可以在一个线程上进行检查,在另一个线程上将事件处理程序设置为 null,现在事件处理程序永远不会被再次调用的假设是 false,因为将在另一个线程上调用过时值!
您不能简单地在本地复制东西并希望得到最好的结果。您必须证明 任何可能的重新排序 您在任意数量的线程 上的读取和写入会产生明智的计划。
The Guid object is a reference type
绝对不是。
C#.NET natively has no copy capabilities from my googling, so what is best-practice in a case such as this?
拿出一把锁。
I can not use a lock
那么你只需要在一个线程上调用你的属性。