c# - 为什么 readonly 和 volatile 修饰符是互斥的?

标签 c# .net multithreading readonly volatile

我有一个只读的引用类型变量,因为引用永远不会改变,只会改变它的属性。当我试图向它添加 volatile 修饰符时,编译警告我它不会让两个修饰符应用于同一个变量。但我认为我需要它是易变的,因为我不想在读取它的属性时出现缓存问题。我错过了什么吗?还是编译器错了?

更新 正如 Martin 在下面的评论之一中所述:在引用类型对象的情况下,readonly 和 volatile 修饰符仅适用于引用,而不适用于对象的属性。那正是我所缺少的,所以编译器是正确的。

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

最佳答案

readonlyvolatile 修饰符都不是穿透性的。它们适用于引用本身,而不适用于对象的属性。

readonly 关键字断言并强制执行,变量 在初始化后不能更改。变量是存储引用的一小块内存。

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

这样应用,可以看出它们确实是互斥的。如果某物是只读的(只能在初始化或构造时写入一次),那么它也不能是易变的(可以由多个线程随时写入)。


关于您对缓存问题的担忧,IIRC,对于编译器何时可以缓存属性调用的结果有非常严格的规定。请记住,它方法调用,并且(从编译器的角度来看)缓存其值并跳过再次调用是一项相当繁重的优化。我不认为这是你需要过分关注的事情。

关于c# - 为什么 readonly 和 volatile 修饰符是互斥的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/396385/

相关文章:

c++ - QThread::wait() 和 QThread::finished()

c# - 限制通用扩展方法扩展字符串

c# - 用于完成默认访问器的 Visual Studio 键盘快捷键 {get;放;}

c# - UseWindowsAzureActiveDirectoryBearerAuthentication 与 UseOpenIdConnectAuthentication 之间有什么区别?

c# - 使用 C# 将变量从线程传递到另一个窗体

c# - 如何使用 BlockingCollection<> 解决生产者/消费者竞争条件

c# - 模型属性作为空值传递给操作

c# - 使用 linq 迭代字段

.net - 访问二级数据库的最佳架构

.net - Gitflow 和测试/部署