C# 线程安全读取Guid两次
我读取Guid对象两次,一次在if语句中,一次在if语句块中 在C语言中,我会在本地复制变量,以确保if语句中的读取操作不会在另一个线程更改该值时读取不同的值 我怀疑以下方法是否是线程安全的,b是否会给我相同的值:C# 线程安全读取Guid两次,c#,.net,guid,C#,.net,Guid,我读取Guid对象两次,一次在if语句中,一次在if语句块中 在C语言中,我会在本地复制变量,以确保if语句中的读取操作不会在另一个线程更改该值时读取不同的值 我怀疑以下方法是否是线程安全的,b是否会给我相同的值: public class MyClass { private Guid MyProp {get;set;} = Guid.Empty; //May be changed at will public OnRunLoop() //Gets called periodicaly on
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是结构而不是引用类型是结构值类型,其大小比原子读取的值长,根据操作系统的不同,原子读取的值为32或64位
因此,如果可以从其他线程更改Guid值,则无法以线程安全的方式读取或写入该值。读取和写入的代码访问Guid必须受到某种同步机制(即锁)的保护
或者,如果您可以保证在所有可能写入该字段的操作都完成之前永远不会发生读取操作,那么基本上使该字段不可变,您就可以在没有锁的情况下读取该字段。如果同一字段有多个可能的写入线程,则始终需要保护对Guid值的写入
在C语言中,我会在本地复制变量,以确保if语句中的读取操作不会在另一个线程在其间更改该值时读取不同的值
我注意到,这种技术只是将一个问题(不一致的读取)替换为另一个问题(陈旧的读取)
这种技术在C多线程事件处理程序中很常见;您经常会看到这样的情况:
var myEvent = this.MyEvent;
if (myEvent != null) myEvent(whatever);
虽然这确实解决了在if和调用之间this.MyEvent发生变化的竞态条件问题,但它并没有解决更深层次的问题:您可以在一个线程上执行检查,在另一个线程上将事件处理程序设置为null,现在假设事件处理程序将永远不会被再次调用,因为将在另一个线程上调用过时的值
你不能简单地把东西复制到本地,然后抱着最好的希望。您必须证明,在任意数量的线程上对读写进行任何可能的重新排序都会产生一个合理的程序
Guid对象是引用类型
绝对不是
C.NET在我的谷歌搜索中没有复制功能,那么在这种情况下,最佳做法是什么呢
拿出一把锁
我不能用锁
然后您只需要在单个线程上调用属性。我认为Guid是一个结构,而不是引用类型。我个人会使用LOCK语句。您可以通过在有问题的代码周围放置锁来确保方法线程安全,这将阻止其他线程进入块,直到处理完成。Guid是一种值类型,您不能依赖于读取是原子的,因此var alocalcopyofprop=MyProp也不安全。我不明白。如果您正在编写MyClass,您怎么可能无法控制MyClass.MyProp。在MyProp setter上使用相同的锁与使用该属性时使用的锁相同,一切都应该正常工作。如果该值来自其他地方,他们将通过MyProp属性将其传递给MyClass实例。只要用lock语句包装属性设置器就行了。如果不能使用锁,那么几乎所有的读取都是过时的,你必须学会以某种方式接受它。锁定对于一个人的理智来说更容易,并且在无争议的场景中不会影响性能。