我有一个引用类型变量readonly
,因为引用永远不会改变,只有它的属性。当我尝试向其添加volatile
修饰符时,编译警告我不会让两个修饰符都应用于同一个变量。但我认为我需要它是易变的,因为我不想在阅读其属性时遇到缓存问题。我错过了什么吗?或编译器错了?
更新正如Martin在以下评论中所述:在参考类型对象的情况下,readonly和volatile修饰符仅适用于引用,而不适用于对象的属性。这就是我所缺少的,所以编译器是正确的。
class C
{
readonly volatile string s; // error CS0678: 'C.s': a field cannot be both volatile and readonly
}
答案 0 :(得分:15)
readonly
和volatile
修饰符都不是渗透性的。它们适用于引用本身,而不是对象的属性。
readonly
关键字断言 - 并强制执行 - 变量在初始化后无法更改。变量是存储引用的小块内存。
volatile
关键字告诉编译器多个线程可能会更改变量的内容。这可以防止编译器使用优化(例如将变量的值读入寄存器并在多个指令上使用该值),这可能会导致并发访问问题。同样,这只会影响存储引用的小块内存。
以这种方式应用,您可以看到它们确实是互斥的。如果某些内容是只读的(只能在初始化或构造时写入一次),那么它也不能是易失性的(可以由多个线程随时写入)。
至于您对缓存问题的关注,IIRC,关于何时编译器可以缓存属性调用的结果,有相当严格的规则。请记住, 是一个方法调用,并且它是一个非常重的优化(从编译器的立场)来缓存它的值并跳过再次调用它。我不认为你需要过多地关注自己。
答案 1 :(得分:1)
只能在首次构造对象时写入只读字段。因此,CPU上不会出现任何缓存问题,因为该字段是不可变的,并且不可能更改。
答案 2 :(得分:0)
虽然引用本身可能是线程安全的,但它的属性可能不是。想想如果两个线程试图同时遍历你的引用对象中的列表会发生什么。