Java 挥发性+;多线程场景中的同步组合
我对Java 挥发性+;多线程场景中的同步组合,java,multithreading,synchronized,volatile,Java,Multithreading,Synchronized,Volatile,我对同步内部结构和易失性内部结构有很好的了解 我有一个问题,是以下问题的后续问题: 我对其中一部分感到困惑。如果我严格遵循上面的示例,我必须将volatile添加到许多变量中,但我确信所有多线程应用程序都没有使用volatile+synchronized组合 如果同步不能保证上述示例中的内存一致性,将volatile变量与synchronizationcode组合使用的用例有哪些?该问题/答案中volatile和synchronized的组合仅适用于双重检查锁定 如果您没有执行双重检查锁定,并
同步
内部结构和易失性
内部结构有很好的了解
我有一个问题,是以下问题的后续问题:
我对其中一部分感到困惑。如果我严格遵循上面的示例,我必须将volatile
添加到许多变量中,但我确信所有多线程应用程序都没有使用volatile+synchronized组合
如果
同步
不能保证上述示例中的内存一致性,将volatile
变量与synchronization
code组合使用的用例有哪些?该问题/答案中volatile
和synchronized
的组合仅适用于双重检查锁定
如果您没有执行双重检查锁定,并且访问共享变量总是在同一个synchronized
监视器的保护范围内(如果应用程序没有使用java.util.concurrent
类,则应用程序最常访问共享变量),那么您就不需要volatile
无论如何,这并不意味着双重检查锁定是一个好主意。虽然
volatile
+synchronized
构造将使双重检查锁定工作,但它没有提供任何显著的性能优势,您也可以在@alf对您所指问题的回答中阅读。该问题/答案中的volatile
和synchronized
组合仅适用于双重检查锁定
如果您没有执行双重检查锁定,并且访问共享变量总是在同一个synchronized
监视器的保护范围内(如果应用程序没有使用java.util.concurrent
类,则应用程序最常访问共享变量),那么您就不需要volatile
无论如何,这并不意味着双重检查锁定是一个好主意。尽管
volatile
+synchronized
构造将使双重检查锁定工作,但它不会提供任何显著的性能优势,因为您也可以在@alf对所指问题的回答中阅读。当定义变量volatile
时,它是从主存而不是注册表读取的
因此,每个处理器将看到相同的值
在双重检查中,变量被定义为volatile
,以确保在synchronized
块之外进行检查将拦截大多数情况
如果变量不是volatile
,代码将正常工作,但如果处理器较多,则可以超出需要进入synchronized
块内部(变量不为null时也是如此)
如果在
synchronized
块中完成了对变量的所有访问,则根本不需要volatile
。定义变量volatile
时,从主存而不是注册表读取变量
因此,每个处理器将看到相同的值
在双重检查中,变量被定义为volatile
,以确保在synchronized
块之外进行检查将拦截大多数情况
如果变量不是volatile
,代码将正常工作,但如果处理器较多,则可以超出需要进入synchronized
块内部(变量不为null时也是如此)
如果在
synchronized
块中完成对变量的所有访问avolatile
完全没有必要。注意:实际上对单例使用双重检查锁定是个坏主意,因为a)单例,b)您可以使用枚举
肯定我使用了一些其他选项,如枚举、惰性加载程序。只是添加了这个问题,通过一些工作代码来提供上下文。我的困惑只是关于组合。双重检查锁定用于单例对象的延迟初始化。此外,volatile可防止可能发生的优化:“此关键字可防止出现编译器试图优化代码的微妙情况,从而在构建完成之前访问对象”(OCP Oracle®Certified Professional Java®SE 8 Programmer II)如果不在单例上使用其他静态方法或变量,则单例的最简单解决方案是使用渴望的解决方案。另一种方法是使用enum,或者使用holder类。注意:实际上对单例使用双重检查锁定是个坏主意,因为a)单例,b)您可以使用enum
肯定我使用了一些其他选项,如enum、惰性加载程序。只是添加了这个问题,通过一些工作代码来提供上下文。我的困惑只是关于组合。双重检查锁定用于单例对象的延迟初始化。此外,volatile可防止可能发生的优化:“此关键字可防止出现编译器试图优化代码的微妙情况,从而在构建完成之前访问对象”(OCP Oracle®Certified Professional Java®SE 8 Programmer II)如果不在单例上使用其他静态方法或变量,则单例的最简单解决方案是使用渴望的解决方案。另一种方法是使用枚举,或者使用holder类,但是在上面的场景中,作者为了内存一致性的目的使用了这种组合。在单锁条件下,上述代码不起作用。@AdityaW上述代码是双重检查锁定,而对于双重检查锁定(在双重检查锁定中,您在synchronized
块之外访问共享变量),您需要volatile
。大多数多线程代码(幸运的是!)没有双重检查锁定,因为它没有什么好处。@AdityaW很好。双重检查代码中的问题源于不同步