java-不正确的延迟初始化

Findbug告诉我,我使用了不正确的延迟初始化。

public static Object getInstance() {

if (instance != null) {

return instance;

}

instance = new Object();

return instance;

}

我在这里没有发现任何问题。 findbug的行为是否错误,还是我错过了一些事情?

8个解决方案

60 votes

Findbug引用了潜在的线程问题。 在多线程环境中,使用当前代码可能会多次创建您的单例。

这里有很多读物,但这将有助于解释。

此处的竞争条件是if check。在第一次调用时,线程将进入if check,并将创建实例并将其分配给“实例”。 但是在if check和实例创建/分配之间,另一个线程可能会变为活动状态。 该线程也可以通过if check,因为分配尚未发生。 因此,将创建两个(或更多,如果有更多线程进入)实例,并且您的线程将引用不同的对象。

nicholas.hauschild answered 2020-01-11T00:06:27Z

18 votes

您的代码比需要的稍微复杂一些,这可能就是为什么造成混淆的原因。

编辑:这绝对是其他人发布的线程问题,但以为我会在此处发布双锁检查实现以供参考:

private static final Object lock = new Object();

private static volatile Object instance; // must be declared volatile

public static Object getInstance() {

if (instance == null) { // avoid sync penalty if we can

synchronized (lock) { // declare a private static Object to use for mutex

if (instance == null) { // have to do this inside the sync

instance = new Object();

}

}

}

return instance;

}

JohnKlehm answered 2020-01-11T00:06:52Z

11 votes

注意:JohnKlehm的双锁检查解决方案更好。 由于历史原因,在此保留此答案。

实际上应该是

public synchronized static Object getInstance() {

if (instance == null) {

instance = new Object();

}

return instance;

}

Varun Achar answered 2020-01-11T00:07:16Z

4 votes

您需要对实例化进行锁定以使其正确

LI:静态字段的不正确的延迟初始化   (LI_LAZY_INIT_STATIC)

此方法包含一个不同步的延迟初始化   非易失性静态场。 因为编译器或处理器可能   重新排序指令,不能保证线程完全看到   初始化的对象,如果该方法可以被多个线程调用。   您可以使字段易变以纠正问题。 欲了解更多   有关信息,请参见Java Memory Model网站。

antlersoft answered 2020-01-11T00:07:45Z

2 votes

感谢John Klehm发布的样本

也可以尝试直接在同步块中分配对象实例

synchronized (MyCurrentClass.myLock=new Object())

private static volatile Object myLock = new Object();

public static Object getInstance() {

if (instance == null) { // avoid sync penalty if we can

synchronized (MyCurrentClass.myLock**=new Object()**) { // declare a private static Object to use for mutex

if (instance == null) { // have to do this inside the sync

instance = new Object();

}

}

}

return instance;

}

jdeveloper answered 2020-01-11T00:08:14Z

2 votes

您错过了多线程问题,

private static Object instance;

public static synchronized Object getInstance() {

return (instance != null ? instance : (instance = new Object()));

}

Nilesh answered 2020-01-11T00:08:34Z

0 votes

您的静态对象未同步。 此外,您的方法不是惰性初始化。 通常,您要做的是保留一个对象地图,并根据需要初始化所需的对象。 因此,您不必在一开始就初始化所有的对象,而不是在需要时调用它们(称为)。

Shahriar answered 2020-01-11T00:08:54Z

0 votes

从1.5开始:实例应该是易失性的,并且您应该集成一个tmp变量,以避免使用已创建但尚未完成其初始化的实例。

private static volatile Object myLock = new Object();

private static volatile Object instance;

public static Object getInstance() {

if (instance == null) {

Object tmpObj;

synchronized (myLock) {

tmpObj = instance;

if (tmpObj == null) {

tmpObj = new Object();

}

}

instance = tmpObj;

}

return instance;

}

user8517281 answered 2020-01-11T00:09:14Z

java 延迟初始化_java-不正确的延迟初始化相关推荐

  1. java 实例变量初始化_java学习之实例变量初始化

    实例变量的初始化方法 第一种:通过构造函数进行初始化. 第二种:通过声明实例字段初始化. 第三种:通过对象代码块初始化. 通过构造函数进行初始化方法 通过构造函数进行对象初始化,必须在类中声明一个带参 ...

  2. java为什么要初始化_JAVA中到底要怎么样初始化

    Java中的变量作用范围: 1. 类的属性,或者叫值域 2. 方法里的局部变量 3. 方法的参数 对于第一种变量,Java虚拟机会自动进行初始化.如果给出了初始值,则初始化为该初始值.如果没有给出,则 ...

  3. java用一个方法对变量初始化_java中怎么给变量初始化?

    展开全部 不同的变量初始化32313133353236313431303231363533e4b893e5b19e31333337613764方法不同. 变量包括:类的属性,或者叫值域 方法里的局部变 ...

  4. 初始化一个java空数组_Java 数组的两种初始化方式

    一.数组 1.数组中存储元素的类型是统一的,每一个元素在内存中所占用的空间大小是相同的,知道数组的首元素的内存地址,要查找的元素只要知道下标,就可以快速的计算出偏移量,通过首元素内存地址加上偏移量,就 ...

  5. java 数组声明并初始化_Java数组的声明与初始化

    在<Java数组简介>一节中,我们已经了解了什么是数组.什么是基本数据类型的数组,那么大家是不是迫不及待地想知道一个基本数据类型的数组是什么样子的呢?下面我们就一起来揭开它神秘的面纱吧! ...

  6. java 接口初始化_Java类和接口的初始化

    类的初始化由执行类中静态代码块的初始化和类中声明的静态域的初始化两部分组成 接口的初始化由接口中声明的域(常量)的初始化组成 初始化的时机 类或接口T在以下任意情况发生之前会立即进行初始化:T是一个类 ...

  7. lambda 延迟执行_Java Lambdas和低延迟

    lambda 延迟执行 总览 有关在Java和低延迟中使用Lambda的主要问题是: 他们会产生垃圾吗,您能做些什么吗? 背景 我正在开发一个支持不同有线协议的库. 这个想法是,您可以描述要写入/读取 ...

  8. java 成员变量的初始化_Java类变量和成员变量初始化过程

    一.类的初始化 对于类的初始化:类的初始化一般只初始化一次,类的初始化主要是初始化静态成员变量. 类的编译决定了类的初始化过程. 编译器生成的class文件主要对定义在源文件中的类进行了如下的更改: ...

  9. java 声明变量 初始化_Java变量的声明和初始化

    Java 语言是强类型(strongly typed)语言,强类型包含以下两方面的含义:所有的变量必须先声明.后使用. 指定类型的变量只能接受类型与之匹配的值. 这意味着每个变量和每个表达式都有一个在 ...

  10. java销毁窗口_java – 如何正确销毁JDialog?

    我目前正在开发一个具有始终存在的主JFrame的工作应用程序.我目前有一个孩子JDialog按下按钮出现.此框架有一个JMenu,其中包含一个"退出显示"的项目.当我按下显示选项的 ...

最新文章

  1. C#笔记24:善用Visual Studio
  2. 脉络最清晰的C++高斯消元程序
  3. .Net 应用程序体系结构—C#高级编程(第10版)学习笔记5
  4. Android中活动Activity方面的知识点
  5. tcp/ip四层和osi七层
  6. python汉字转拼音代码_Python 汉字转换拼音代码
  7. ORACLE PL/SQ入门
  8. SPOJ 2939 Query on a tree V
  9. html5 video标签嵌入视频
  10. 最优化进退法c语言编程,进退法、0.618法、Powell法、罚函数法的程序设计,急!!...
  11. C语言中如何在不使用数组的情况下求方差?使用数组和使用for循环的区别。
  12. css开启3d加速的属性,开启3D加速,提高游戏速度
  13. java释放线程资源_Java线程之释放锁,释放资源,释放CPU
  14. 论文数据统计Task1
  15. python的函数导入方法
  16. 遗传算法(GA/NSGA)优化神经网络 GA-BP
  17. 【数据处理】超好用的Excel数据拆分工具
  18. 产品、技术:如何编写有效的流程文档?
  19. STM32CubeMx笔记--P2. LED亮晶晶
  20. 计算机维修中拆机工具有哪些,秒变专业拆机维修达人,这款工具套装你值得拥有...

热门文章

  1. a different object with the same identifier value was already associated with the session解决方案
  2. ORACLE 字符串超长问题解决方案
  3. jquery中ajax请求后台数据成功后既不执行success也不执行error解决方法
  4. idea无法搜索插件问题解决
  5. flask from app import db ImportError: cannot import name ‘db’ 的解决方案
  6. 将UTC日期时间转换为本地日期时间
  7. 返回,返回无,根本没有返回?
  8. 字符串的UPDATE和REPLACE部分
  9. Java线程池了解一下
  10. 雅虎成立特别委员会评估新战略选项