关于Java关键字synchronized——单例模式的思考

      精彩的设计模式盛宴刚刚落下帷幕,三天的时间,真是学习到了很多。其中,遗留的很多的问题。今天就谈谈synchronized这个关键字。关于对synchronized关键字的思考是从单例模式引发的。在代码中利用延迟加载,将对象的初始化定义为null值,在需要的时候才去进行对象的构造,getinstance这个方法。这个就是我们经常说的懒汉式单例模式。


懒汉式单例的出现:


        如果将类初始化的过程放到代码运行中,有好处,就是启动快,如果对象实例化过程比较复杂,这样可以提供效率,速度,当用到的时候再去创建对象。但是懒汉式单例模式同样存在一个问题,打个比方说:线程A希望使用SingletonClass,调用getInstance()方法。因为是第一次调用,A就发现instance是null的,于是它开始创建实例,就在这个时候,CPU发生时间片切换,线程B开始执行,它要使用SingletonClass,调用getInstance()方法,同样检测到instance是null——注意,这是在A检测完之后切换的,也就是说A并没有来得及创建对象——因此B开始创建。B创建完成后,切换到A继续执行,因为它已经检测完了,所以A不会再检测一遍,它会直接创建对象。这样,线程A和B各自拥有一个SingletonClass的对象——单例失败!


Synchronized同步锁引出:


    通过介绍延迟加载再到懒汉式,终于引出了我们今天要讲的主题,那么如何解决上面一个关于创建对象时,CPU切换的问题呢?其实方法很简单,就是将这个GetInstance方法加锁,是要getInstance()加上同步锁,一个线程必须等待另外一个线程创建完成后才能使用这个方法,这就保证了单例的唯一性。

   两个并发线程访问同一个对象obj中的synchronized修饰的一个方法时,一个时间内只能有一个线程得到执行,即A操作完才可以让B操作,否则B一直处于等待的状态中,也可以说是一种阻塞的状态。


对应代码可以是:

public class SingletonClass { 

  private static SingletonClass instance = null; 
    
  public synchronized static SingletonClass getInstance() { 
    if(instance == null) { 
      instance = new SingletonClass(); 
    } 
    return instance; 
  } 
    
  private SingletonClass() { 
     
  } 
    
}



什么时候用到synchronized?


   在编写一个类时,如果该类中的代码可能运行于多线程环境下,那么就要考虑同步的问题。在Java中内置了语言级的同步原语--synchronized,这也大大简化了Java中多线程同步的使用。锁不仅仅可以用到类的实例化,也可以用到静态成员方法的声明中。


synchronized优缺点?

    通过它的优点可以看出它的缺点是什么,优点是将解决多线程的问题,避免占用资源,占用多个对象。相对缺点是会锁住某一段程序,别的程序如果需要调用的话就必须等待,减少了速度、效率。有可能产生死锁,导致程序中断。


小结:

    之前对于单例模式的了解只是知道它可以用于实例化一个窗体对象,有且只有一个对象被实例化出来。现在学过了J2SE的线程那一章,本来也是晕晕的,不理解这个同步锁。当再一次回顾这个单例模式的时候,结合着synchronized的定义,我了解到了很多,跟之前的学习产生的共鸣。效果很好。


你可能感兴趣的:(1.J2SE)