`
thrillerzw
  • 浏览: 143938 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

单例模式线程安全

    博客分类:
  • java
 
阅读更多

线程安全问题:这里指的是获取单例对象时候的问题,不是对象共享资源修改时候的问题。

 

双重锁定:“二次判断” ,不用每个线程在执行这个方法之前都会去等待获得锁。

如果不加同步,多个线程创建多个对象的问题,后一个覆盖前一个。 

if(instance==null) 
{
instance=new Singleton();
}

    private Singleton(){}
	private volatile static Singleton instance = null;
	public static Singleton getInstance() {
		if (instance == null) {
                    //synchronized (this)   
	             synchronized (Singleton.class) {
				if (instance == null) {
					instance = new Singleton();
				}
			}
		}
		
		return instance;
	} 

 

 

 类加载时候初始化对象: 不能延迟加载(对象大的时候,是一种空间浪费),适合类初始化时候就需要加载的场景。

public class Singleton { 

private Singleton(){ 
  
} 
//也可以不用加final,加上也行。因为私有构造方法,和私有属性可以保证其它类调用不会修改instance 。
private static Singleton instance =new Singleton(); 
public static Singleton getInstance(){ 
      return instance; 
} 

} 

  

 

static 内部类,延迟加载,使用虚拟机同步机制,不需要加synchronized 

 

public class Singleton    
{    
    private static class SingletonHolder    
    {    
        public final static Singleton instance = new Singleton();    
    }    
   
    public static Singleton getInstance()    
    {    
        return SingletonHolder.instance;    
    }    
}  

 

 

 

 

0
7
分享到:
评论
23 楼 teasp 2013-05-25  
thrillerzw 写道
teasp 写道
thrillerzw 写道
class
chenzenghua 写道
public class Singleton {
                
                 private Singleton(){}
                
                 private static class SingletonHolder{
                                 private static Singleton instance = new Singleton();
                }
                
                 public static Singleton getInstance(){
                                 return SingletonHolder.instance;
                }
}

详见《研磨设计模式》5.3.8节

我感觉加上内部类比较麻烦。这样做有什么好处呢。

他这个是延迟加载,利用静态内部类延迟初始化。好处就是不用双重检查,也不用synchronized。

延迟加载是个优点,问题是不用synchronized,怎么保证多个线程同时获得对象,修改共享数据呢??

这就是静态内部类的作用。SingletonHolder被加载的时候其实隐含了synchronized,加载完毕,实例已经初始化完成。因此这里不是不用synchronized,而是用了类加载机制的synchronized。
22 楼 thrillerzw 2013-05-25  
teasp 写道
thrillerzw 写道
class
chenzenghua 写道
public class Singleton {
                
                 private Singleton(){}
                
                 private static class SingletonHolder{
                                 private static Singleton instance = new Singleton();
                }
                
                 public static Singleton getInstance(){
                                 return SingletonHolder.instance;
                }
}

详见《研磨设计模式》5.3.8节

我感觉加上内部类比较麻烦。这样做有什么好处呢。

他这个是延迟加载,利用静态内部类延迟初始化。好处就是不用双重检查,也不用synchronized。

延迟加载是个优点,问题是不用synchronized,怎么保证多个线程同时获得对象,修改共享数据呢??
21 楼 lvwenwen 2013-05-24  
你的代码里面可以不用synchronized
20 楼 lection.yu 2013-05-24  
chenzenghua 写道
public class Singleton {
                
                 private Singleton(){}
                
                 private static class SingletonHolder{
                                 private static Singleton instance = new Singleton();
                }
                
                 public static Singleton getInstance(){
                                 return SingletonHolder.instance;
                }
}

详见《研磨设计模式》5.3.8节

正解
19 楼 teasp 2013-05-24  
animalfishyu 写道
teasp 写道
animalfishyu 写道
。。。。。。

你给的链接里面抛弃了双重检查锁,其实双重检查锁在java里面还是可以用的,只不过写法要注意一点点。



每种写法都有优缺点。

不是优缺点的问题,是正确性的问题。
18 楼 teasp 2013-05-24  
liuyuhua0066 写道
teasp 写道
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
 
private static Singleton instance =new Singleton();  
 
public static synchronized Singleton getInstance(){
      if (null == instance)
      {
            synchronized (Singleton.class)
            {
                if (null == instance)
                {
                     instance = new Singleton();
                }
            }
      }
      return instance;  


另外注意instance 的可见性问题,建议加上volatile关键字

你这个比楼主写得要差啊。楼主的代码去掉了synchronized也没有可见性的问题。你的纯属多此一举。


说这个多此一举的麻烦看看设计模式

看到你让我看设计模式本来想笑的,但是处于谨慎还是看了懒汉的单例,没见到有加synchronized的。
17 楼 caizi12 2013-05-24  
teasp 写道
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
。。。。。。。。。。。。。



说的都有问题,他这种写法本身都不太合理,加双重锁前提是,private static Singleton=null; 没有实例化才这样写。
可以参考这个帖子,四种单例模式的写法。
http://blog.sina.com.cn/s/blog_75247c770100yxpb.html

你给的链接里面抛弃了双重检查锁,其实双重检查锁在java里面还是可以用的,只不过写法要注意一点点。



每种写法都有优缺点。
16 楼 teasp 2013-05-24  
caizi12 写道
teasp 写道
animalfishyu 写道
teasp 写道
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
 
private static Singleton instance =new Singleton();  
 
public static synchronized Singleton getInstance(){
      if (null == instance)
      {
            synchronized (Singleton.class)
            {
                if (null == instance)
                {
                     instance = new Singleton();
                }
            }
      }
      return instance;  


另外注意instance 的可见性问题,建议加上volatile关键字

你这个比楼主写得要差啊。楼主的代码去掉了synchronized也没有可见性的问题。你的纯属多此一举。

嗯,是的,楼主这个是已经给属性赋值了,如果是懒加载,我的写法会好些

如果是懒加载,你的写法是不好的,为什么要两个synchronized?方法上都已经有了synchronized,那么就没必要双重检查。如果去掉方法上的synchronized,你的写法就不是线程安全的了。




说的都有问题,他这种写法本身都不太合理,加双重锁前提是,private static Singleton=null; 没有实例化才这样写。
可以参考这个帖子,四种单例模式的写法。
http://blog.sina.com.cn/s/blog_75247c770100yxpb.html

你给的链接里面抛弃了双重检查锁,其实双重检查锁在java里面还是可以用的,只不过写法要注意一点点。
15 楼 animalfishyu 2013-05-24  
caizi12 写道
animalfishyu 写道
caizi12 写道
teasp 写道
animalfishyu 写道
teasp 写道
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
 
private static Singleton instance =new Singleton();  
 
public static synchronized Singleton getInstance(){
      if (null == instance)
      {
            synchronized (Singleton.class)
            {
                if (null == instance)
                {
                     instance = new Singleton();
                }
            }
      }
      return instance;  


另外注意instance 的可见性问题,建议加上volatile关键字

你这个比楼主写得要差啊。楼主的代码去掉了synchronized也没有可见性的问题。你的纯属多此一举。

嗯,是的,楼主这个是已经给属性赋值了,如果是懒加载,我的写法会好些

如果是懒加载,你的写法是不好的,为什么要两个synchronized?方法上都已经有了synchronized,那么就没必要双重检查。如果去掉方法上的synchronized,你的写法就不是线程安全的了。




说的都有问题,他这种写法本身都不太合理,加双重锁前提是,private static Singleton=null; 没有实例化才这样写。
可以参考这个帖子,四种单例模式的写法。
http://blog.sina.com.cn/s/blog_75247c770100yxpb.html

呵呵,直接复制了楼主的代码,不好意思,方法上不能加synchronized,我这样的做法,是为了让后续线程如果在对象已经不为空了,而不用去等待锁的获得,多谢提醒



方法加锁最大问题就是有性能问题,。

嗯,是的,锁的粒度很重要,这种讨论很有意义
14 楼 teasp 2013-05-24  
caizi12 写道
teasp 写道
animalfishyu 写道
teasp 写道
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
 
private static Singleton instance =new Singleton();  
 
public static synchronized Singleton getInstance(){
      if (null == instance)
      {
            synchronized (Singleton.class)
            {
                if (null == instance)
                {
                     instance = new Singleton();
                }
            }
      }
      return instance;  


另外注意instance 的可见性问题,建议加上volatile关键字

你这个比楼主写得要差啊。楼主的代码去掉了synchronized也没有可见性的问题。你的纯属多此一举。

嗯,是的,楼主这个是已经给属性赋值了,如果是懒加载,我的写法会好些

如果是懒加载,你的写法是不好的,为什么要两个synchronized?方法上都已经有了synchronized,那么就没必要双重检查。如果去掉方法上的synchronized,你的写法就不是线程安全的了。




说的都有问题,他这种写法本身都不太合理,加双重锁前提是,private static Singleton=null; 没有实例化才这样写。
可以参考这个帖子,四种单例模式的写法。
http://blog.sina.com.cn/s/blog_75247c770100yxpb.html

我的问题在那里?有了private static Singleton=null;双重检查锁就有问题。我不推荐双重锁的方式,大部分人都写不对。
13 楼 caizi12 2013-05-24  
animalfishyu 写道
caizi12 写道
teasp 写道
animalfishyu 写道
teasp 写道
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
 
private static Singleton instance =new Singleton();  
 
public static synchronized Singleton getInstance(){
      if (null == instance)
      {
            synchronized (Singleton.class)
            {
                if (null == instance)
                {
                     instance = new Singleton();
                }
            }
      }
      return instance;  


另外注意instance 的可见性问题,建议加上volatile关键字

你这个比楼主写得要差啊。楼主的代码去掉了synchronized也没有可见性的问题。你的纯属多此一举。

嗯,是的,楼主这个是已经给属性赋值了,如果是懒加载,我的写法会好些

如果是懒加载,你的写法是不好的,为什么要两个synchronized?方法上都已经有了synchronized,那么就没必要双重检查。如果去掉方法上的synchronized,你的写法就不是线程安全的了。




说的都有问题,他这种写法本身都不太合理,加双重锁前提是,private static Singleton=null; 没有实例化才这样写。
可以参考这个帖子,四种单例模式的写法。
http://blog.sina.com.cn/s/blog_75247c770100yxpb.html

呵呵,直接复制了楼主的代码,不好意思,方法上不能加synchronized,我这样的做法,是为了让后续线程如果在对象已经不为空了,而不用去等待锁的获得,多谢提醒



方法加锁最大问题就是有性能问题,。
12 楼 animalfishyu 2013-05-24  
caizi12 写道
teasp 写道
animalfishyu 写道
teasp 写道
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
 
private static Singleton instance =new Singleton();  
 
public static synchronized Singleton getInstance(){
      if (null == instance)
      {
            synchronized (Singleton.class)
            {
                if (null == instance)
                {
                     instance = new Singleton();
                }
            }
      }
      return instance;  


另外注意instance 的可见性问题,建议加上volatile关键字

你这个比楼主写得要差啊。楼主的代码去掉了synchronized也没有可见性的问题。你的纯属多此一举。

嗯,是的,楼主这个是已经给属性赋值了,如果是懒加载,我的写法会好些

如果是懒加载,你的写法是不好的,为什么要两个synchronized?方法上都已经有了synchronized,那么就没必要双重检查。如果去掉方法上的synchronized,你的写法就不是线程安全的了。




说的都有问题,他这种写法本身都不太合理,加双重锁前提是,private static Singleton=null; 没有实例化才这样写。
可以参考这个帖子,四种单例模式的写法。
http://blog.sina.com.cn/s/blog_75247c770100yxpb.html

呵呵,直接复制了楼主的代码,不好意思,方法上不能加synchronized,我这样的做法,是为了让后续线程如果在对象已经不为空了,而不用去等待锁的获得,多谢提醒
11 楼 caizi12 2013-05-24  
teasp 写道
animalfishyu 写道
teasp 写道
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
 
private static Singleton instance =new Singleton();  
 
public static synchronized Singleton getInstance(){
      if (null == instance)
      {
            synchronized (Singleton.class)
            {
                if (null == instance)
                {
                     instance = new Singleton();
                }
            }
      }
      return instance;  


另外注意instance 的可见性问题,建议加上volatile关键字

你这个比楼主写得要差啊。楼主的代码去掉了synchronized也没有可见性的问题。你的纯属多此一举。

嗯,是的,楼主这个是已经给属性赋值了,如果是懒加载,我的写法会好些

如果是懒加载,你的写法是不好的,为什么要两个synchronized?方法上都已经有了synchronized,那么就没必要双重检查。如果去掉方法上的synchronized,你的写法就不是线程安全的了。




说的都有问题,他这种写法本身都不太合理,加双重锁前提是,private static Singleton=null; 没有实例化才这样写。
可以参考这个帖子,四种单例模式的写法。
http://blog.sina.com.cn/s/blog_75247c770100yxpb.html
10 楼 liuyuhua0066 2013-05-24  
teasp 写道
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
 
private static Singleton instance =new Singleton();  
 
public static synchronized Singleton getInstance(){
      if (null == instance)
      {
            synchronized (Singleton.class)
            {
                if (null == instance)
                {
                     instance = new Singleton();
                }
            }
      }
      return instance;  


另外注意instance 的可见性问题,建议加上volatile关键字

你这个比楼主写得要差啊。楼主的代码去掉了synchronized也没有可见性的问题。你的纯属多此一举。


说这个多此一举的麻烦看看设计模式
9 楼 teasp 2013-05-24  
animalfishyu 写道
teasp 写道
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
 
private static Singleton instance =new Singleton();  
 
public static synchronized Singleton getInstance(){
      if (null == instance)
      {
            synchronized (Singleton.class)
            {
                if (null == instance)
                {
                     instance = new Singleton();
                }
            }
      }
      return instance;  


另外注意instance 的可见性问题,建议加上volatile关键字

你这个比楼主写得要差啊。楼主的代码去掉了synchronized也没有可见性的问题。你的纯属多此一举。

嗯,是的,楼主这个是已经给属性赋值了,如果是懒加载,我的写法会好些

如果是懒加载,你的写法是不好的,为什么要两个synchronized?方法上都已经有了synchronized,那么就没必要双重检查。如果去掉方法上的synchronized,你的写法就不是线程安全的了。
8 楼 animalfishyu 2013-05-24  
teasp 写道
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
 
private static Singleton instance =new Singleton();  
 
public static synchronized Singleton getInstance(){
      if (null == instance)
      {
            synchronized (Singleton.class)
            {
                if (null == instance)
                {
                     instance = new Singleton();
                }
            }
      }
      return instance;  


另外注意instance 的可见性问题,建议加上volatile关键字

你这个比楼主写得要差啊。楼主的代码去掉了synchronized也没有可见性的问题。你的纯属多此一举。

嗯,是的,楼主这个是已经给属性赋值了,如果是懒加载,我的写法会好些
7 楼 teasp 2013-05-24  
thrillerzw 写道
class
chenzenghua 写道
public class Singleton {
                
                 private Singleton(){}
                
                 private static class SingletonHolder{
                                 private static Singleton instance = new Singleton();
                }
                
                 public static Singleton getInstance(){
                                 return SingletonHolder.instance;
                }
}

详见《研磨设计模式》5.3.8节

我感觉加上内部类比较麻烦。这样做有什么好处呢。

他这个是延迟加载,利用静态内部类延迟初始化。好处就是不用双重检查,也不用synchronized。
6 楼 teasp 2013-05-24  
animalfishyu 写道
其实你没觉得synchronized 方法代价有些过高么,每个线程在执行这个方法之前都会去等待获得锁,执行之后释放锁,建议锁粒度变小,采用比较常用的“二次判断”
 
private static Singleton instance =new Singleton();  
 
public static synchronized Singleton getInstance(){
      if (null == instance)
      {
            synchronized (Singleton.class)
            {
                if (null == instance)
                {
                     instance = new Singleton();
                }
            }
      }
      return instance;  


另外注意instance 的可见性问题,建议加上volatile关键字

你这个比楼主写得要差啊。楼主的代码去掉了synchronized也没有可见性的问题。你的纯属多此一举。
5 楼 thrillerzw 2013-05-24  
class
chenzenghua 写道
public class Singleton {
                
                 private Singleton(){}
                
                 private static class SingletonHolder{
                                 private static Singleton instance = new Singleton();
                }
                
                 public static Singleton getInstance(){
                                 return SingletonHolder.instance;
                }
}

详见《研磨设计模式》5.3.8节

我感觉加上内部类比较麻烦。这样做有什么好处呢。
4 楼 chenzenghua 2013-05-24  
public class Singleton {
                
                 private Singleton(){}
                
                 private static class SingletonHolder{
                                 private static Singleton instance = new Singleton();
                }
                
                 public static Singleton getInstance(){
                                 return SingletonHolder.instance;
                }
}

详见《研磨设计模式》5.3.8节

相关推荐

    Java 单例模式线程安全问题

    Java 单例模式线程安全问题详解 Java 单例模式线程安全问题是指在 Java 中实现单例模式时,如何确保线程安全的问题。单例模式是指在整个应用程序生命周期中,只有一个实例存在的设计模式。这种模式可以提高性能,...

    Java中懒汉单例设计模式线程安全测试

    Java中懒汉单例设计模式线程安全测试,单例设计模式的测试

    单例模式线程安全的三种表达

    单例模式三种线程安全的表达方式,其中枚举方式的单例是最安全的

    线程安全的单例模式

    ### 线程安全的单例模式详解 #### 一、单例模式简介 单例模式(Singleton Pattern)是软件开发中最常用的创建型设计模式之一,它的主要目标是确保一个类只有一个实例,并提供一个全局访问点。单例模式在很多场景下...

    使用C++11实现线程安全的单例模式

    线程安全的单例模式在多线程环境下尤其重要,因为不正确的实现可能导致多个线程创建多个实例,这违反了单例模式的基本原则。C++11引入了新的特性,如std::mutex和std::call_once,使得实现线程安全的单例模式变得...

    c++单例模式线程日志类

    在C++编程中,单例模式是一种常用的软件设计模式,它保证一个类只有一个实例,并提供一个全局访问点。在这个特定的场景中,我们讨论的是一个实现了单例模式的日志类,该类专为多线程环境设计,具备日志等级控制、...

    浅议单例模式之线程安全(转)

    在多线程环境下,线程安全的单例模式尤为重要,因为如果不正确实现,可能会导致多个线程同时创建多个实例,违反了单例模式的基本原则。 在Java中,单例模式通常有以下几种实现方式: 1. 饿汉式(静态常量): ...

    C++两种线程安全的单例模式的实现

    使用"懒汉模式"与"饿汉模式"实现c++的单例模式,并且确保了单例模式的第一次实例化的线程安全,以及程序结束时,单例对象的资源收回,以防内存资源的泄漏

    synchronized与单例的线程安全

    "synchronized"关键字和单例模式是确保线程安全的两种常见手段。本文将详细探讨这两个概念及其在实现线程安全中的作用。 一、synchronized关键字 synchronized是Java中的一个关键同步机制,用于控制对类或对象的...

    unity中涉及的三种单例模式

    下面将详细介绍在Unity中涉及的三种单例模式:C#经典单例、Unity内置单例以及一种线程安全的改进版单例。 1. C#经典单例: 这是最常见的单例实现方式,通常通过私有构造函数和一个静态方法来保证只有一个实例。在...

    7种单例模式

    单例模式是软件设计模式中的一种经典模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式在很多场景下非常有用,比如控制共享资源、管理配置对象等。下面将详细介绍七种常见的单例模式实现...

    详解python实现线程安全的单例模式

    然而,如果我们想要在类级别实现线程安全的单例模式,就需要考虑多线程环境下的并发问题。 在给出的代码中,首先定义了一个装饰器`Singleton`,它的目的是确保每次调用时返回的是同一个实例。装饰器内部维护了一个...

    多线程单例模式并发访问

    总结起来,多线程环境下的单例模式实现需要注意线程安全问题,尤其是懒汉式单例,需要采取适当的同步措施来防止多线程环境下的实例化问题。此外,对于不同场景的需求,可以选择不同的实现方式来优化性能和资源使用。

    设计模式之单例模式(结合工厂模式)

    单例模式是软件设计模式中的一种经典模式,它保证了类只有一个实例存在,并提供一个全局访问点。在Java等面向对象编程语言中,单例模式常用于管理共享资源,如数据库连接池、线程池或者配置文件等。结合工厂模式,...

    Java设计模式之单例模式的七种写法

    Java设计模式之单例模式的七种写法 单例模式是一种常见的设计模式,它确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机的驱动程序对象常...

    C#单例模式详解 C#单例模式详解C#单例模式详解

    单例模式是软件设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。在C#中,单例模式常用于管理共享资源或控制类的实例化过程,以提高性能、节约系统资源,特别是在整个应用程序生命周期内只需要一...

    java单例模式实例

    单例模式是软件设计模式中的一种经典模式,用于确保一个类只有一个实例,并提供一个全局访问点。在Java中,有多种实现单例模式的方法,每种都有其特点和适用场景。接下来,我们将深入探讨这些实现方式。 首先,我们...

    Qt两种方法实现多线程并安全结束线程及QMutex加锁Qt单例化实现

    本主题将详细探讨如何使用Qt的QThread类来创建和管理线程,并且安全地结束线程,同时结合QMutex进行线程同步,以及如何实现Qt的单例模式。 1. **QThread的使用**: - **创建线程**: 在Qt中,创建线程通常是通过...

    设计模式——单例模式

    **设计模式——单例模式** 在软件工程中,设计模式是一种在特定场景下解决常见问题的标准方案,可以被复用并提升代码质量。单例模式是设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。这种模式...

Global site tag (gtag.js) - Google Analytics