最近在公司写需求时遇到了多线程与单例一同出现的情况。

这个时候想到的就是线程安全以及单例的定义了,虽然单例指的是在内存中它只有一份,但是并不是说就是线程安全的。

所以,我当时就到网上找了关于多线程下单例的线程安全问题的资料,然后就知道如下博客:高并发下线程安全的单例模式(最全最经典)

其中,博主最推荐的写作方式如下:

为了达到线程安全,又能提高代码执行效率,这里可以采用DCL(Double Check Locking)的双检查锁机制来完成

public class MySingleton {  

    //使用volatile关键字保其可见性
volatile private static MySingleton instance = null; private MySingleton(){} public static MySingleton getInstance() {
try {
if(instance != null){//懒汉式 }else{
//创建实例之前可能会有一些准备性的耗时工作
Thread.sleep(300);
synchronized (MySingleton.class) {
if(instance == null){//二次检查
instance = new MySingleton();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return instance;
}
}

看了看内容确实是这个道理,然后就把这段代码拿来使用了。然后在实际测试中发现,其并没有保证线程安全的问题。

之后在同事的指点下发现,其实上文一段的线程安全仅仅只是在未实例化单例的前提下,以线程安全的方式实例化单例,使之在高并发多线程的环境下有且仅被new过一次。

也就是说,在单例被实例化之后,这段代码是并没有什么作用的。

单例被实例化之后,instance != null一直成立,使getInstance()每次都是return instance。所以,多线程都能拿到指向同一个实例的引用。

所以即使是使用了这种双检查锁机制的代码,依然要对后面要使用到的公用方法做同步,以免出现问题。

而对公用方法做同步的操作也分两种情况。一种是公用方法里只有局部变量,那么此时不做同步也是可以的,因为局部变量只会存在于相应的线程内存里,并不会被其它线程所影响。另外一种是含有成员变量,如果成员变量只有读的操作,那不同步也可以;如果成员变量涉及读写操作,那么就要对相应的方法进行同步了。

局部变量不会受多线程影响
成员变量会受到多线程影响

多个线程应该是调用的同一个对象的同一个方法:
如果方法里无成员变量,那么不受任何影响
如果方法里有成员变量,只有读操作,不受影响
                      存在写操作,考虑多线程影响值

来源:关于多个线程同时调用单例模式的对象,该对象中方法的局部变量是否会受多个线程的影响

Java-多线程与单例的更多相关文章

  1. Java 多线程之单例设计模式

    转载:https://segmentfault.com/a/1190000007504892 概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍两种:懒汉式单例.饿汉 ...

  2. JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

    JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...

  3. Java设计模式之单例

    一.Java中的单例: 特点: ① 单例类只有一个实例 ② 单例类必须自己创建自己唯一实例 ③ 单例类必须给所有其他对象提供这一实例 二.两种模式: ①懒汉式单例<线程不安全> 在类加载时 ...

  4. Java复习11. 单例编程

    Java复习11. 单例编程 1.最简单的写法,那个方式是线程不安全的 public class Singleton {     private static Singleton instance; ...

  5. java中的单例设计模式

    单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供 ...

  6. Java开发之单例设计模式

    设计模式之单例模式: 一.单例模式实现特点:①单例类在整个应用程序中只能有一个实例(通过私有无参构造器实现):②单例类必须自己创建这个实例并且可供其他对象访问(通过静态公开的访问权限修饰的getIns ...

  7. Java笔记(十一)……单例设计模式

    设计模式 解决某一类问题最行之有效的方法 Java中有23中设计模式 单例设计模式 解决一个类在内存中只存在一个对象 思路 将构造函数私有化 在类中创建一个本类对象 提供一个方法可以获取到对象 两种方 ...

  8. java设计模式_单例

    public class Singleton { public static void main(String[] args) throws Exception { System.out.printl ...

  9. 转载:java基础之单例

    转载:https://blog.csdn.net/goodlixueyong/article/details/51935526 https://www.cnblogs.com/cielosun/p/6 ...

  10. java基础28 单例集合Collection下的List和Set集合

    单例集合体系: ---------| collection  单例集合的根接口--------------| List  如果实现了list接口的集合类,具备的特点:有序,可重复       注:集合 ...

随机推荐

  1. POST信息模拟登录获取页面内容

    最近项目里有一个是要模拟登录后,访问固定页面获取内容的要求,一开始用JQ AJAX好像不支持跨域请求.后使用.net中HttpWebRequest对象来获取.一开始访问总是无法在第二个页面正常访问,好 ...

  2. Android(java)学习笔记61:Android中的 Application类用法

    1. 简介 如果想在整个应用中使用全局变量,在java中一般是使用静态变量,public类型:而在android中如果使用这样的全局变量就不符合Android的框架架构,但是可以使用一种更优雅的方式就 ...

  3. IOError: [Errno 22] invalid mode ('rb') or filename: 'C

    dataset = scipy.io.loadmat('F:\test_data.mat') 报错 IOError: [Errno ] invalid mode ('rb') or filename: ...

  4. B4260 Codechef REBXOR

    真是6块钱cpu(笑 爆炸入口 踹树练习(汗 对于二进制异或和弹性,我们可以贪心的来做. 瓶颈在于快速贪心. 我们可以维护一个trie树,储存异或前缀和.每次在trie树上贪心的跑. 正向and反向跑 ...

  5. HttpHandler(处理程序) 和 HttpModule(托管模块)

    本文参见:http://www.tracefact.net/Asp-Net/Introduction-to-Http-Handler.aspx 前言:前几天看到一个DTcms网站,里面有个伪静态技术, ...

  6. AngularJS 外部文件中的控制器

    在大型的应用程序中,通常是把控制器存储在外部的文件中. <!DOCTYPE html><html><head><meta http-equiv="C ...

  7. AngularJS 重复HTML元素

    data-ng-repeat指令会重复一个HTML元素 <!DOCTYPE html><html><head><meta http-equiv="C ...

  8. fcc初级算法方法总结

    var arr = str.split("分隔符"): var newArr = arr.reverse(); var str = arr.join("连接符" ...

  9. Eclipse使用的小技巧

    1.在右键new菜单栏中添加新建JSP文件 window->perspective->customize perspective->shortcuts->web->把JS ...

  10. Chrome 调试工具的一些高阶功能

    Chrome 内置抓包工具 Block requests 截取长图 代码的覆盖率分析 Make site better Chrome 内置抓包工具 在浏览器地址栏输入chrome://net-inte ...