【发布时间】:2014-05-28 19:48:32
【问题描述】:
是否可以通过在属性访问器中使用Interlocked 来获得线程安全的属性?
例子:
public class A()
{
private static long count;
public static long Count
{
get
{
return Interlocked.Read(ref count);
}
set
{
Interlocked.Exchange(ref count, value);
}
}
}
【问题讨论】:
-
“线程安全”是整个程序的属性,而不仅仅是其中的一个 sn-p,在您明确明确定义“线程安全”的含义之前,它也不是一个特别有意义的术语",表示在整个程序中将/不会满足哪些条件。话虽如此,我会说一般来说,看到这样的属性是代码气味。这对我来说是一个信号,有人认为某些东西会正常工作,而实际上它不会,尽管需要查看该属性的每一次使用才能确定。
-
关于示例代码的“线程安全”,唯一可以说的是,Count 的值是由属性集实际分配给它的值(如果您用简单的分配和返回替换联锁)。但是,正如 Servy 所说,如果您不准确定义您所谈论的“线程安全”属性,那并没有多大意义。
-
@MaMazav 你甚至不能这么说,真的。
Interlocked.Read有可能返回一个值,将其存储在临时文件中,调用 setter,更改值,然后让 getter 返回,因此您甚至不能说 getter 不返回一个陈旧的价值。添加的内存屏障有助于它不会作为陈旧,并防止重新排序获取和设置来自同一线程,但是当涉及多个线程时,您仍然可以由于在返回值之前将值存储在临时(隐式完成)中,因此可以做一些非常时髦的事情。 -
原子性和线程安全是不同的概念,你从这段代码中得到的原子性保证是非常弱的。您所拥有的只是一个保证,当您的程序在 32 位模式下运行时,您将永远不会读取部分更新的值。
-
@Servy 我唯一的主张是他编写的代码承诺返回值必须是过去分配给它的值(而不是部分分配,如 HansPassant 所说)。我不明白如何将值存储在临时文件中。
标签: c# multithreading thread-safety interlocked