/** * 单例模式涉及的两个问题 * * @author 罗摩衔那 * */ /* * 恶汉式 * 优点:当类被加载的时候,已经创建好了一个静态的对象,因此,是线程安全的 * 缺点:这个对象还没有被使用就被创建出来了 */ class Single { private static final Single s=new Single();// private Single() {}//私有无参构造方法 public static Single getInstance() { return s; } } /* * 懒汉式 * 优点:按需加载对象,只有对象被使用的时候才会被创建 缺点:这种写法不是线程安全的,例如当第一个线程执行判断语句if(s = null)时, 第二个线程执行判断语句if(s = null),接着第一个线程执行语句test = new Test(), 第二个线程也执行语句test = new Test(),在这种多线程环境下,可能会创建出来两个对象 */ class Singler { private static Singler s=null; private Singler() {}; public static /*synchronized*/ Singler getInstance() { /* * 一.-->线程0 -->线程1 当线程0进入创建对象 * 线程1进入不用判断也创建对象--出问题 * 二.当给函数加上同步性质synchronized后,线程进入,不为空 * 也就不判断,那么就不用创建对象,问题解决 * 三.下面加同步锁是为了线程安全问题 * 最外面再加一次判断是为了效率问题 */ if(s==null) { synchronized(Singler.class) { if(s==null) s=new Singler(); } } return s; } } public class SingleDemo { public static void main(String[] args) { System.out.println("Hello World!"); } }
第三种情况时:进入线程0,判断是否为null,获得线程锁占位,再判断是null创建对象,返回一个s.
假设线程0释放执行权,线程1判断完后,是进不来的--因为0线程的执行资格还没释放,接着释放执资格.
接着线程1进入,判断为null,获得线程锁占位,再次判断s不为空.