【发布时间】:2012-01-29 13:13:51
【问题描述】:
我对 volatile 的引用类型感到困惑。
我知道对于原始类型,volatile 可以立即反映来自另一个线程的值更改。对于引用类型,它可以立即反映地址的变化。但是,对象的内容呢?它们是否仍被缓存?
(假设List.Add()是原子操作)
例如,我有:
class A
{
volatile List<String> list;
void AddValue()
{
list.Add("a value");
}
}
如果一个线程调用函数AddValue,列表的地址没有改变,另一个线程是否会更新列表的“内容”变化,或者内容可能为每个线程缓存而不是更新其他线程?
【问题讨论】:
-
我不确定这一点,但我的猜测是,鉴于该列表实际上只是一个指针(地址),当内容更新时,它会立即反映在任何地方,因为内容将驻留在堆,然而,随着地址的改变,堆栈被改变了,我认为它可以驻留在一个核心上。但是,如前所述,没有专家。这只是一个猜测。
-
另外,作为旁注。大量优化的易失性转变。很多优化。有些人强烈建议不要使用 volatile 修饰符,而是在需要时使用 volatileread 和 volatilewrite(在系统命名空间中的类上找到的一些全局静态方法,可能在 google 上可以找到)。
-
@Alxandr:小心点。易失性读取和易失性写入是调用的潜在昂贵方法,它们会引发全栅栏,而不是人们期望的半栅栏。如果您出于性能原因编写无锁代码(以及您必须做这件疯狂的事情的其他原因是什么?),那么 VolatileRead 和 VolatileWrite 完全有可能更糟。你必须仔细分析它。
-
volatile 修饰符在 all 上诱导 volatile 读写,是的 ALL,对字段进行读写,但使用 volatile 读写是可选的。此外,afaik,易失性读写总是比锁定快至少 10 倍,而且它不会以任何方式做同样的事情。至少那是我关于 .NET 线程的视频告诉我的(我认为是在 lidnug 上找到的)。
-
现在去找一个视频来解释你不同意/争论的人...... :)