2008-12-28 29 views
8

我有一个引用类型的变量,即readonly,因为引用永远不会改变,只有它的属性。当我试图将volatile修饰符添加到它时,编译警告我不会让这两个修饰符应用于相同的变量。但我认为我需要它是不稳定的,因为我不想在阅读它的属性时发生缓存问题。我错过了什么?还是编译器错了?为什么readonly和volatile修饰符是互斥的?

更新正如马丁在下面的注释之一中所述:readonly和volatile修饰符只应用于引用,而不适用于引用类型对象的对象属性。这就是我所错过的,所以编译器是正确的。

class C 
{ 
    readonly volatile string s; // error CS0678: 'C.s': a field cannot be both volatile and readonly 
} 
+0

编译器[潜在错误](http://stackoverflow.com/q/39004125/1149773)(尽管可能不适用于您的特定场景)。 – Douglas 2016-08-17 19:37:11

回答

14

修饰符不是readonly也不是volatile修饰符是渗透性的。它们适用于参考本身,而不适用于对象的属性。

readonly关键字断言 - 并强制执行 - 变量在初始化后无法更改。该变量是存储引用的小块内存。

volatile关键字告诉编译器,变量的内容可能会被多个线程改变。这可以防止编译器使用可能会导致并发访问问题的优化(例如将变量值读入寄存器并在多条指令中使用该值)。同样,这只影响存储引用的小块内存。

以这种方式应用,你可以看到它们确实是互斥的。如果某些东西是只读的(只能在初始化或构造时写入一次),那么它不能是易失性的(可以由多个线程随时写入)。


至于你提到缓存问题,IIRC的关注,大约有当编译器可以高速缓存的属性调用的结果相当严格的规定。请记住,它是的一个方法调用,它是一个非常重的优化(从编译器的立场)缓存它的值并跳过再次调用它。我不认为这是你需要过多关注的事情。

1

只读对象首次构建时,只能写入只读字段。因此,在CPU上不会有任何缓存问题,因为该字段是不可变的,并且不可能改变。

+0

我理解你的逻辑,但我不同意。一个对象可以是只读的,并且仍然通过其属性进行更改,因为它的属性不是只读的。在这种情况下只读属性只能防止将该变量分配给另一个对象。至少是我从我所了解的内容中了解到的。 – 2008-12-28 17:09:01

+2

@Vernict:readonly和volatile修饰符只保护引用(或者在原子值为bool,int的情况下的值),而不是对象的内容!这是一个完全不同的问题。 – 2008-12-28 17:13:15

0

虽然引用本身可能是线程安全的,但它的属性可能不是。想想看,如果两个线程试图同时遍历包含的参考对象的之内会发生什么情况。

+0

但这是既不是只读也不是挥发性的东西。无论如何,这是你需要解决的问题。 – 2008-12-28 17:11:29

相关问题