(49)静态同步函数的锁是Class对象,例子:懒汉式--在多线程中存在问题--同步解决

一、如果同步函数被静态修饰后,使用的锁是什么呢?
通过验证,发现使用的不是this.因为静态方法中也不可以定义this
静态进内存,内存中没有本类对象,但是一定个该类对应的字节码文件对象。
类名.class 该对象的类型为Class.
静态的同步方法,使用的锁是该方法所在类的字节码文件兑现,类名.class
二、懒汉式—-在多线程中存在安全问题

class Single 
{
      private static Single s=null;
      private Single(){}
      public static Single getInstance(){
      if(s==null)
            s=new Single();
       return s;
      }
}

这个静态方法被run调用后,存在安全问题原因:
s是个共享数据,当一个线程执行到if(s==null)时,判为真时,cpu执行其他的程序去了,比如此时另一个线程,此时执行if(s==null),因为刚才的线程并没有创建对象,所以判断为真,这样就会创建两个对象,存在安全问题

将此函数改为同步函数,就可以解决这个问题。
class Single
{
private static Single s=null;
private Single(){}
public static synchronized Single getInstance(){
if(s==null)
s=new Single();
return s;
}
}

但是这样会使得多线程运行效率低,原因是加锁多个判断条件。

class Single 
{
      private static Single s=null;
      private Single(){}
      public static  Single getInstance(){
      if(s==null)
          {
             synchronized(Single.class)
             {
                  if(s==null)
                      s=new Single();
              }
          }

       return s;
      }
}

为什么在synchronized中也要写个if(s==null)呢?
举个栗子说明:
第一个线程在外层if判断成功后,进入同步块,判断内部的if,成立,此次CPU被剥夺,比如执行到第二个线程,同样判断外层的if,因为上同步块上着锁,进不了,隔一段时间,第一个线程得到cpu,继续执行,创建了对象,开锁。然后隔一段时间,第二个线程继续执行,进入共享区,然后if(s==null)判断失败,开锁,这就防止了创建对个对象。因为只有一个对象,所以以后的外层if (s==null)
都判断失败,因为已经有对象了,这样就摆脱了在多线程中使用同步方法、,每次都判断是否有锁,运行效率有所提高。

posted @ 2017-07-12 16:07  测试开发分享站  阅读(139)  评论(0编辑  收藏  举报