c# - Java 中的双重检查锁定是否需要 `volatile` 而不是 C#?

标签 c# java volatile double-checked-locking

在 Java 程序员中众所周知,为了使双重检查锁定正确运行,必须将变量声明为 volatile,并且同步对象的初始化是不够的。

这种意识可能主要是因为 volatile 关键字的语义在 1.5 中被更改为包含“发生在之前”的关系,至少部分是为了使双重检查锁定安全;据我了解,“先发生”关系意味着写入 volatile 变量会导致线程中的所有缓存变量都写入主内存,并且在从 volatile 变量读取后,所有缓存变量都被认为是陈旧的,并且必须从主内存中重新读取,以便在写入 volatile 变量之前写入的所有内容都保证“发生在”稍后从该变量读取之前。

堆栈溢出 seems to believe对于 C#,volatile 对于双重检查锁定来说是不必要的(尽管注意到这可能特定于某些 CPU 或 Microsoft 的实现),同时也相信 Java 的 synchronized 语义 语句是 exactly the same作为 C# 的 lock 语句,这表明在 Java 中发现的相同问题也将存在于 C# 中,除非两种语言之间双重检查锁定的语义存在其他一些主要差异。

那么……哪个是正确的? C# 中的双重检查锁定实际上没有 Java 中的危险吗?如果是这样,是什么语言语义不同使情况如此?

如果不是,如果没有 volatile,具体会出现什么问题? C# 中 volatile 的语义是否像 Java 一样建立了“发生之前”的关系,因此双重检查锁定在 C# 中与 volatile 一样安全,就像在 Java 中一样从 1.5 开始?

最佳答案

来自 MSDN :“volatile 关键字表示一个字段可能会被同时执行的多个线程修改。声明为 volatile 的字段不受假设由单个线程访问的编译器优化的影响。这确保了最新的-日期值始终存在于字段中。”

因此,volatile 仅在您从多个线程更改变量值时才有用。如果你 lock() 使用同一个锁定对象访问共享资源的代码区域,你保证只有一个线程可以同时访问这些代码区域,那么除非你正在修改锁定对象(这是一个非常糟糕的主意),否则不需要 volatile .

关于c# - Java 中的双重检查锁定是否需要 `volatile` 而不是 C#?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23072422/

相关文章:

c# - 帮助 Linq to Xml 查询

c# - System.Security.Cryptography.RSA.Encrypt 方法中是否假定 MGF1 填充与 RSAEncryptionPadding.OaepSHA256?

c# - Visual Studio - 调试与发布

c# - 鉴于 doubles 不能用于 volatile 字段,这是一个安全的选择吗?

java - volatile Java 重新排序

c# - Asp.net (MVC) 和 WPF (MVVM) 的比较 - 是否有等效的数据绑定(bind)?

java - 如何在 Java 中执行 C++ 中更改重写方法可见性的操作?

java - 超能力规则语言: return datafield of class from pattern

java - 如果进程超过分配的时间,如何杀死进程

c# - 在线程应用程序中使用 C# Volatile 关键字