懒汉模式学习线程处理
来源:互联网 发布:电脑电音软件 编辑:程序博客网 时间:2024/06/01 08:07
package kaadas.example.com.bluetooth;/** * Created by ty on 2017/8/15. */public class BluetoothMananger { /** * 4. volatile是否有必要? * volatile 会拒绝编译器对其修饰的变量进行优化。也就不会存在重排序的问题。volatile只会影响可见性,不会影响原子性。 * <p> * 如果只判断一次null==instance的话,就没必要了。但如果像本博客代码里写的那样,判断了两次null==instance,那么 * volatile是必要的。为什么呢?举个反例,假设线程thread1走到了第33行(外层if)的if判断发现instance==null成立, * 于是都进入了外部的if体。 * 这时候thread1先获取了synchronized块的锁,于是thread1线程会执行第43行的instance = new SingleTon();这句代码, * 问题就出在这里,这条语句它不是原子性执行的。在Java里,实例化一个对象的过程简单地讲,可以分为两步1) * 先为instance对象分配一块内存,2)在这块内存里为instance对象里的成员变量赋值(比如第28行里为url赋值)。 * 假设当thread1执行完第1)步而还没有执行第2)步的时候,另外一个线程thread2走到了第15行(外层if), * 这时候instance已经不是null了,于是thread2直接返回了这个instance对象。有什么问题呢?instance对象的初始化 * (变量赋值等操作)还没执行完呢!thread2里直接得到了一个没有初始化完全的对象,就有可能导致很严重的问题了。 * 那么volatile关键字有啥作用呢?当用volatile修饰了instance变量之后,对instance的写操作”先行发生“于对它的读操作。 * (这是Java虚拟机里的先行发生原则,不明白的网友可以留言或是看看Java虚拟机的相关资料。)这样就保证了, * thread1中的instance变量被完全初始化之后,thread2才能读取它,当没有完成初始化时,thread2只能等会儿啦。 */ private volatile static BluetoothMananger instance; private final String url; private BluetoothMananger() { instance = new BluetoothMananger(); url = "http://www.laomiaopu.com"; } public static BluetoothMananger getInstance() { if (null == instance) { /** * 1. 一般用synchronized修饰getInstance()方法就可以了,干嘛要把synchronized块写到函数体里呢? 原因如下:假设BluetoothMananger这个类还有个synchronized的static函数f1(),那么,一旦调用f1()正在进行的时候, SingleTon的class对象会被锁住,故而getInstance()方法就要等待了。同理,一旦调用getInstance()正在进行的时候, f1()就无法被调用,只能等待getInstance()执行完了才能执行。所以把synchronized写到函数里面,实际上是减小了 锁的粒度。这样当instance已经被实例化了的时候,getInstance()这个函数是不会加锁的,故不影响f1()函数的调用。 */ synchronized (BluetoothMananger.class) { if (null == instance) { instance = new BluetoothMananger(); } } } return instance; } public static synchronized void f1() { System.out.println("第二条线程工作!"); System.out.println("http://www.laomiaopu.com"); }}/** * 2. 为啥要判断两次null == instance呢?把第15(外层的if)行的外层if判断去掉不行吗? * 行!去掉也不会出错,但是如果判断两次性能更好。因为如果只判断一次的话,每次执行getInstance() * 函数都要对synchronized块进行加锁;而如果进行两次判断的话,只有第一次调用的时候(即instance==null) * 的时候会对synchronized块进行加锁,其他时候(如果发现instance!=null)是不需要加锁的。 * <p> * <p> * 3.把第25行的内部if判断去掉不行吗?不行!很有可能当外层判断的时候,instance确实是null; * 但是到了synchronized块中,执行第26行的instance = new BluetoothMananger();的时候,instance已经被其他的线程给实例化了。 * <p> * <p> * 没有内部if情况下,如果两个线程同时执行getInstance(),判断 instance都不为null后, 进入if判断语句. * 这个时候一个线程获得锁, 然后进入new了一个对象, 并开心的执行完了. 这个时候另外一个线程获得了锁, * 但让它也不会再去判断 instace是否为null, * 所以它也会再执行一次new操作. 所以这里执行了两次new操作. 当然最后instance还是只指向后一次new的对象. */
阅读全文
1 0
- 懒汉模式学习线程处理
- 同步线程 懒汉式单例设计模式
- 懒汉式单例模式的线程安全问题
- 懒汉式单例设计模式线程不安全
- 设计模式之懒汉单例非线程安全
- Java 多线程学习笔记(十一) 单例设计模式(延迟加载/懒汉模式)DCL解决线程安全问题
- 单例模式(懒汉模式)中的线程同步问题
- 单例模式之懒汉模式的线程安全解决方法
- 懒汉模式
- 单例模式--饿汉式、懒汉式、线程安全的懒汉式、高性能安全的懒汉式
- 解决单例设计模式中懒汉式线程安全问题
- JAVA单例(懒汉模式)线程安全
- 线程简介--单利模式饿汉式和懒汉式
- 解决单例设计模式中懒汉式线程安全问题
- 设计模式 Singleton 单例 懒汉,线程安全
- 单例模式 (懒汉式, 线程同步详解)
- 线程安全的单例懒汉模式(互斥锁)
- 设计模式系列(7)线程下的懒汉式单例
- win10+python3.6安装numpy,scipy,scikit-learn,matplotlib
- 集群与分布式数据库
- Cash Machine(poj-1276)(多重背包)
- javaMail发送邮件设置发件人中文昵称
- Oracle 登录链接数据库,查询建立directory文件,并授读写权限
- 懒汉模式学习线程处理
- 解决圆角问题
- SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
- 内联函数解读
- 自用读取配置文件工具类ReadConfig
- 揭秘!东莞五星酒店“卖赢”案一哥一审宣判:老板“太子辉”被判无期
- 【问题】Font 'STSongStd-Light' with 'UniGB-UCS2-H' is not recognized
- 工作中遇到关于WebView的效果
- 如何在网页上获取用户的当前位置[仅限移动端网页]