您的位置:首页 > 其它

处理单例设计模式中懒汉式的安全问题过程

2014-07-13 13:56 204 查看
设计模式:解决某一类问题最行之有效的方式。Java中有23中设计模式。单例设计模式目的:解决一个类在内存中对象的唯一性。

解决方案:

1.为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象

2.还为了让其他程序可以访问该类对象,只好在本类中自定义一个对象

3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。

以上三个步骤实现过程:

1.将构造函数私有化,

2.在类中创建一个本类对象,

3.提供一个方法,可以获取该对象

单力设计模式有两种模式:“饿汉式”和“懒汉式”。

饿汉式:类一经加载进内存就创建对象。如代码示例-1

代码示例-1

class Single
{
private static final Single s = new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}
懒汉式:类加载后没有创建对象,类调用getInstance方法后创建对象,这种现象叫做对象的延迟加载。如代码示例-2

代码示例-2
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)
s = new Single();
return s;
}
}
但是懒汉式,在多线程中会出现安全问题。假设A,B两个线程并发访问getInstacne()方法,因为有多条语句操作共享数据s,一个在判断另一个在赋值。当线程A判断为null,此

时A线程假设遇到sleep语句睡了一会。被线程B抢到执行权,线程B进来也sleep了,A醒后创建一个对象赋给s,(if语句只判断一次)B醒后向下执行,又创建个对象。单例设计模

式的目的要保证一个类在内存中对象的唯一性,new了很多对象,所以不安全。此时想到了同步,将getInstance()函数变为同步函数,这样A线程进来后,B线程就进不来。所

以当A线程new一个对象赋给s出去后,B进来判断s不为null,就不new对象,直接返回s使用。这样就解决了安全问题,如代码示例-3

代码示例-3

class Single
{
private static Single s = null;
private Single(){}
public static synchronized Single getInstance()
{
if(s==null)
s = new Single();
return s;
}
}
但是又考虑到,如果有n多线程并发访问getInstance()方法想获取实例,每次调用都要判断锁,判断锁的次数会非常多,导致代码运行速度降低。为了解决这个问题,采用双重

判断的方式,当A线程进来后,先判断s是否为空,如果为空在持有锁后可能sleep一会,B线程没有持有锁,不能进来A线程醒后,new一个对象出去释放锁,B线程持有锁来,

判断st不为null,直接使用s,以后其他所有线程调用getInstance()方法,判断s不为空,就直接使用s,这种方式锁只判断了一次,解决了程序运行低的问题。如代码示例-4

代码示例-4
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;
}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐