iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java单例模式中的线程安全问题
  • 842
分享到

Java单例模式中的线程安全问题

2024-04-02 19:04:59 842人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录一. 使用多线程需要考虑的因素?二. 单例模式?1. 饿汉模式?2. 懒汉模式?3. 懒汉模式(使用synchronized改进)4. 懒汉模式(使用双重校验锁改进)三. vol

一. 使用多线程需要考虑的因素

提高效率:使用多线程就是为了充分利用CPU资源,提高任务的效率
线程安全:使用多线程最基本的就是保障线程安全问题

所以我们在设计多线程代码的时候就必须在满足线程安全的前提下尽可能的提高任务执行的效
故:
加锁细粒度化:加锁的代码少一点,让其他代码可以并发并行的执行

?考虑线程安全:

没有操作共享变量的代码没有安全问题
对共享变量的读,使用volatile修饰变量即可
对共享变量的写,使用synchronized加锁

?二. 单例模式

单例模式能保证某个类在程序中只存在唯一一份实例,而不会创建出多个实例
例如:DataSource(数据连接池),一个数据库只需要一个连接池对象

单例模式分为饿汉模式和懒汉模式

?1. 饿汉模式

饿汉模式是在类加载的时候就创建实例
这种方式是满足线程安全的(JVM内部使用了加锁,即多个线程调用静态方法,只有一个线程竞争到锁并且完成创建,只执行一次)

实现代码:

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

?2. 懒汉模式

懒汉模式是在类加载的时候不创建实例,第一次使用的时候才创建

实现代码:

public class Singleton {
    private static Singleton instance = null;
    private Singleton(){
 
    }
    public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

观察上述代码,在单线程下不存在线程安全问题,但是在多线程环境下存在安全问题吗? 

分析:
?当实例没有被创建的时候,如果有多个线程都调用getInstance方法,就可能创建多个实例,就存在线程安全问题 
?但是实例一旦创建好,后面线程调用getInstance方法就不会出现线程安全问题

结果:线程安全问题出现在首次创建实例的时候

?3. 懒汉模式(使用synchronized改进)

我们使用sychronized修饰,?‍?️代码如下:

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

这样实现线程安全存在什么问题呢?

解析:
我们对方法使用synchronized修饰,也就是每次调用该方法的时候都会竞争锁,但是创建实例只需要创建一次,也就是创建实例后,再调用该方法还需要竞争锁释放锁

结果:虽然满足线程安全,但是效率低

4. 懒汉模式(使用双重校验锁改进)

在上述代码的基础上进行改动:

使用双重if判定,降低竞争锁频率
使用volatile修饰instance 

实现代码:

public class Singleton {
    private static volatile Singleton instance = null;
    private Singleton(){
 
    }
    public static synchronized Singleton getInstance(){
        if(instance == null){ //外层的if判断:如果实例被创建直接return,不让线程再继续竞争锁
            //在没有创建实例时,多个线程已经进入if判断了
            //一个线程竞争到锁,其他线程阻塞等待
            synchronized (Singleton.class) {
                //内层的if判断,目的是让竞争失败的锁如果再次竞争成功的话判断实例是否被创建,创建释放锁return,没有则创建
                if(instance == null){ 
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

?对双重if的解析:

?外层的if判断:实例只是被创建一次,当实例已经被创建好了就不要后续操作,直接return返回
?内层的if判断:实例未被创建时,多个线程同时竞争锁,只有一个线程竞争成功并创建实例,其他竞争失败的线程就会阻塞等待,当第一线程释放锁后,这些竞争失败的线程就会继续竞争,但是实例已经创建好了,所以需要再次进行if判断 

画图分析,如下所示:

三. volatile的原理 

volatile保证了可见性,有序性,在Java层面看,volatile是无锁操作,多个线程对volatile修饰的变量进行读可以并发并行执行,和无锁执行效率差不多

volatile修饰的变量中,CPU使用了缓存一致性协议来保证读取的都是最新的主存数据 

缓存一致性:如果有别的线程修改了volatile修饰的变量,就会把CPU缓存中的变量置为无效,要操作这个变量就要从主存中重新读取

?四. volatile的扩展问题(了解)

?如果说volatile不保证有序性,双重校验锁的写法是否有问题?

关于new对象按顺序分为3条指令:

?(1) 分配对象的内存空间
?(2) 实例化对象
?(3) 赋值给变量

正常的执行顺序为(1)(2)(3),JVM可能会优化进行重排序后的顺序为(1)(3)(2)

这个重排序的结果可能导致分配内存空间后,对象还没有实例化完成,就完成了赋值
在这个错误的赋值后,instance==null不成立,线程就会拿着未完成实例化的instance,使用它的属性和方法就会出错

使用volatile保证有序性后:

线程在new对象时不管(1)(2)(3)是什么顺序,后续线程拿到的instance是已经实例化完成的
CPU里边,基于volatile变量操作是有CPU级别的加锁机制(它保证(1)(2)(3)全部执行完,写回主存,再执行其他线程对该变量的操作)

 到此这篇关于Java单例模式中的线程安全问题的文章就介绍到这了,更多相关Java单例模式线程安全内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java单例模式中的线程安全问题

本文链接: https://www.lsjlt.com/news/151980.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java单例模式中的线程安全问题
    目录一. 使用多线程需要考虑的因素二. 单例模式1. 饿汉模式2. 懒汉模式3. 懒汉模式(使用synchronized改进)4. 懒汉模式(使用双重校验锁改进)三. volatil...
    99+
    2024-04-02
  • Java 单例模式线程安全问题
    Java 单例模式线程安全问题SpringIOC容器默认提供bean的访问作用域是单例模式。即在整个application生命周期中,只有一个instance。因此在多线程并发下,会有线程安全风险。我们在MVC框架下的servlet就是线程...
    99+
    2023-05-31
    java 单例模式 线程安全
  • Java单例模式中的线程安全问题怎么解决
    今天小编给大家分享一下Java单例模式中的线程安全问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一. 使用多线程...
    99+
    2023-07-02
  • 浅谈单例模式和线程安全问题
    目录单例模式、多实例模式、和线程安全单例模式懒汉式和饿汉式对比多线程模式下的安全性多实例模式总结单例模式、多实例模式、和线程安全 单例模式 单例模式是指确保一个类仅有一个唯一的实例,...
    99+
    2023-05-14
    java单例模式 java线程安全
  • java单例模式和线程安全问题怎么解决
    这篇文章主要介绍“java单例模式和线程安全问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“java单例模式和线程安全问题怎么解决”文章能帮助大家解决问题。单例模式、多实例模式、和线程安全...
    99+
    2023-07-05
  • PHP中单例模式的线程安全性问题思考
    在PHP编程中,单例模式是一种常用的设计模式,它可以确保一个类只有一个实例,并且提供一个全局的访问点来访问这个实例。然而,在多线程环境下使用单例模式时,需要考虑线程安全性的问题。单例模式的最基本实现包括一个私有的构造函数、一个私有的静态变量...
    99+
    2023-10-21
    单例模式 PHP编程 线程安全性
  • 使用springboot单例模式与线程安全问题踩的坑
    springboot单例模式与线程安全问题踩的坑 最近有客户反映,使用公司产品时,偶尔会存在崩溃情况,自己测试无问题,然后去查日志,是报空指针。 于是顺藤摸瓜 往上找,好嘛,之前的开...
    99+
    2024-04-02
  • Java单例模式的线程安全,饿汉和懒汉模式详解
    单例模式 创建唯一的一个变量(对象),在类中将构造函数设为protected或者private(析构函数设为相对应的访问权限),故外部不能实例化对象,再提供访问它的一个全局访问点,即...
    99+
    2024-04-02
  • Java中线程安全问题
    目录一.线程不安全二.那些情况导致了线程不安全?三.Java中解决线程不安全的方案1.volatile“轻量级”解决线程不安全2.synchronized自动加锁四.公平锁与非公平锁...
    99+
    2024-04-02
  • Java多线程中线程安全问题的示例分析
    这篇文章主要介绍了Java多线程中线程安全问题的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1. 什么是线程安全和线程不安全?什么是线程安全呢?当多个线程并发访问某...
    99+
    2023-06-29
  • java中线程安全问题举例分析
    这篇文章主要讲解了“java中线程安全问题举例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java中线程安全问题举例分析”吧!一、什么时候数据在多线程并发的环境下会存在安全问题?三个条...
    99+
    2023-06-21
  • Java实现线程安全单例模式的五种方式的示例代码
    目录饿汉式枚举单例懒汉式DCL 懒汉式静态内部类懒汉单例饿汉式 饿汉式:类加载就会导致该单实例对象被创建 // 问题1:为什么加 final // 问题2:如果实现了序列化接口, 还...
    99+
    2024-04-02
  • java中SimpleDateFormat非线程安全问题的示例分析
    小编给大家分享一下java中SimpleDateFormat非线程安全问题的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!SimpleDateFormat非线程安全问题实现1000个线程的时间格式化package&...
    99+
    2023-06-20
  • 单例模式在PHP中并发访问的线程安全性处理思路
    然而,在并发访问的情况下,单例模式可能存在线程安全性问题。当多个线程同时请求获取单例对象时,可能会出现竞争条件,导致获得的实例不一致或者创建多个实例。为了解决这个问题,我们需要考虑如何保证单例模式在并发访问时的线程安全性。一种常见的解决方案...
    99+
    2023-10-21
    单例模式 线程安全性 并发访问 处理思路
  • Java多线程之线程安全问题
    文章目录 一. 线程安全概述1. 什么是线程安全问题2. 一个存在线程安全问题的程序 二. 线程不安全的原因和线程加锁1. 案例分析2. 线程加锁2.1 理解加锁2.2 synchroni...
    99+
    2023-09-21
    java 线程安全 多线程 synchronized jvm
  • java面试常见模式问题---单例模式
    目录1、简介2、单例模式——懒汉式3、单例模式——饿汉式总结1、简介 单例模式使⽤场景: 业务系统全局只需要⼀个对象实例,⽐如发号...
    99+
    2024-04-02
  • Java中单例模式与多线程的示例分析
    这篇文章主要介绍了Java中单例模式与多线程的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。单例模式与多线程单例模式就是全局唯一但是所有程序都可以使用的对象写单例模式...
    99+
    2023-06-20
  • 详谈ThreadLocal-单例模式下高并发线程安全
    目录ThreadLocal-单例模式下高并发线程安全为了解决线程安全的问题,我们有3个思路:多线程中的ThreadLocal1.ThreadLocal概述2. ThreadLocal...
    99+
    2024-04-02
  • Java中的多线程如何实现单例模式
    这期内容当中小编将会给大家带来有关Java中的多线程如何实现单例模式,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Java多线程中的单例模式一、在多线程环境下创建单例方式一:package com.iet...
    99+
    2023-05-31
    java 线程 单例模式
  • 聊聊java多线程创建方式及线程安全问题
    什么是线程 线程被称为轻量级进程,是程序执行的最小单位,它是指在程序执行过程中,能够执行代码的一个执行单位。每个程序程序都至少有一个线程,也即是程序本身。 线程的状态 新建(New)...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作