黑马程序员技术交流社区

标题: 饿汉式和懒汉式问题(已解决) [打印本页]

作者: 古银平    时间: 2012-5-21 09:25
标题: 饿汉式和懒汉式问题(已解决)
本帖最后由 古银平 于 2012-5-21 14:11 编辑

饿汉式,对象在类一进内存时就加载,懒汉式在方法调用时才加载对象,他们在内存中运行的区别是什么?
懒汉式在运行时会出现点问题,突然cpu转向别的程序,A,B,C三个来判断if(s==null),将会出现可能创建多个对象问题,该怎么解决?
作者: 袁培育    时间: 2012-5-21 09:48
饿汉式与懒汉式在内存中的区别:饿汉式一旦被加载进内存便建立自己的本类对象,懒汉式在被加载进内存后先建立一个空的本类引用,在调用其方法时再进行判断,若引用为空则建立对象并返回,若不为空则直接返回。
懒汉式在多线程技术中会出现不同步问题,就需要用到synchronized进行同步。
作者: 何旭栋    时间: 2012-5-21 09:56
用synchronized()加锁
作者: 黑马-唐磊    时间: 2012-5-21 10:35
1:它们在内存运行区别是饿汉式类一加载对象就存在内存中了,懒汉式是我创建一个一个静态变量,变量已经存在但没有值只有调用getIntance时对象才存在内存中。
2:要解决你的第二个问题就要用到synchronized()同步了,因为懒汉式是多线程并发访问的,所以出现不同步问题
作者: 袁錦泰    时间: 2012-5-21 10:43
本帖最后由 袁錦泰 于 2012-5-21 10:51 编辑
  1. /*它们之间的区别上面的同学已经和你说明了我就不再赘述了
  2. *我着重对懒汉式在避免线程安全问题上进行说明
  3. */
  4. public class Single {

  5.         private Single() {

  6.         }

  7.         private static Single s = null;

  8.         public static Single getInstance() {
  9.                 // -->line B
  10.                 if (s == null) { // -->line A
  11.                         s = new Single();
  12.                 }
  13.                 return s;
  14.         }
  15. }

  16. /*
  17. * 1,两个线程并发调用函数getInstance(),lineA判断s为null,然后向下执行
  18. * 2,这时JVM将CPU切换到lineB,由于lineA还未执行创建对象语句,所以s依然为null
  19. * 3,lineB执行了new Single()语句后,lineA被重新唤醒,也执行了new Single()语句
  20. * 4,单例设计模式此时创建出两个对象,问题就这样产生了
  21. * 如何解决呢?代码如下:
  22. */
  23. public class Single {
  24.         private Single() {

  25.         }

  26.         private static Single s = null;

  27.         public synchronized static Single getInstance() {
  28.                 if (s == null) {
  29.                         s = new Single();
  30.                 }
  31.         }
  32. }

  33. /*
  34. * 在方法中加入同步修饰符,线程的安全问题得到解决,但代码的性能被大大降低了
  35. * 除了第一次调用getInstance()时执行了Single的构造函数外,以后每次调用都是返回s对象
  36. * 返回对象耗时很小,但每次判断同步就恰恰相反了
  37. * 如何优化这段代码的性能问题呢?代码如下:
  38. */
  39. public class Single {
  40.         private Single() {

  41.         }

  42.         private static Single s = null;

  43.         public static Single getInstance() {
  44.                 synchronized (Single.class) {
  45.                         if (s == null) {
  46.                                 s = new Single();
  47.                         }
  48.                 }
  49.         }
  50. }

  51. /*
  52. * 不难发现,将同步写为代码块的形式之后,每次调用getInstance()都需要对其进行判断
  53. * 由于只需第一次创建s时进行同步,所以可以修改为下面的写法:
  54. */
  55. public class Single {
  56.         private Single() {

  57.         }

  58.         private static Single s = null;

  59.         public static Single getInstance() {
  60.                 if (s == null) {
  61.                         synchronized (Single.class) {
  62.                                 if (s == null) {
  63.                                         s = new Single();
  64.                                 }
  65.                         }
  66.                 }
  67.         }
  68. }
  69. /*
  70. * 修改至此,只能保证代码的性能问题得到部分解决,其实这样使用单例设计模式依然存在问题
  71. * 所以我们得到了最终的解决方案,代码如下:
  72. */
  73. public class Single {
  74.         private Single() {

  75.         }

  76.         private static Single s = new Single();

  77.         public static Single getInstance() {
  78.                 return s;
  79.         }
  80. }
  81. /*
  82. * 我曾经上网查找过相关资料
  83. * 关于懒汉式单例设计模式提到了计算机CPU的执行顺序是乱序的,所以依然可能在运行中报错
  84. * 具体为什么还会出现问题至今我还是不太理解,所以我不敢在这里卖弄
  85. * 你只需知道在写单例设计模式的时候用饿汉式就可以
  86. * 希望这样一个对代码的说明加修改过程对你理解懒汉式单例涉及模式有帮助
  87. */
复制代码

作者: 黑马张健    时间: 2012-5-21 10:45
区别:
饿汉式:先初始化对象,Single类一进内存,就创建对象。
懒汉式:对象方法被调用时,才初始化,也叫做对象的延时加载。Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象。
运用同步锁 ,去锁定不安全的代码。
这样可以避免出现CUP跳转后发生的异常现象。
作者: --☆伟☆--    时间: 2012-5-21 11:33
懒汉式与饿汉式都是单例模式,目的是限制随意建立对象,两者的区别,在于:
1.饿汉式随着类的加载建立对象,而懒汉式则是在调用时才建立对象,按照毕老师的说法,相对饿汉式,懒汉能节约少许内存
2.但懒汉式有一个硬伤就是你所说到的多线程cpu跳转问题,针对这个问题的解决方案就是加锁进行同步处理,具体请参考毕老师多线程教学视频
PS:两者各有优劣,不过据几个搞开发的朋友说他们喜欢的是饿汉式,当然,你要是运存控的话,用懒汉也是不错选择


作者:  夜风    时间: 2012-5-21 12:20
毕老师的视频里有讲到,synchronized锁来解决,面试中可能会遇到,实际开发中用不到。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2