当前位置: 首页 > news >正文

淄博城乡建设局网站如何做360搜索网站

淄博城乡建设局网站,如何做360搜索网站,wordpress瀑布流,健身器材 网站模版单例模式 单例模式确保某个类在程序中只有一个实例#xff0c;避免多次创建实例#xff08;禁止多次使用new#xff09;。 要实现这一点#xff0c;关键在于将类的所有构造方法声明为private。 这样#xff0c;在类外部无法直接访问构造方法#xff0c;new操作会在编译… 单例模式 单例模式确保某个类在程序中只有一个实例避免多次创建实例禁止多次使用new。 要实现这一点关键在于将类的所有构造方法声明为private。 这样在类外部无法直接访问构造方法new操作会在编译时报错从而保证类的实例唯一性。例如在JDBC中DataSource实例通常只需要一个单例模式非常适合这种场景。 单例模式的实现方式主要有两种“饿汉式”和“懒汉式” 饿汉模式 下面这段代码是对唯一成员 instance 进行初始化用 static 修饰 instance对 instance 的初始化会在类加载的阶段触发类加载往往就是在程序一启动就会触发 由于是在类加载的阶段就早早地创建好了实例(static修饰)这也就是“饿汉模式” 名字的由来。 在初始化好 instance 后后续统一通过调用 getInstance() 方法获取 instance 单例模式的“点睛之笔”用 private 修饰类中所有构造方法因为可以防止通过 new 关键字在类外部创建实例只能通过调用内部静态方法来获取单例类实例 懒汉模式 饿汉模式在类加载时即创建实例通过将构造方法声明为private防止外部创建其他实例。懒汉模式延迟创建实例仅在真正需要时才创建。这种模式在某些情况下无需实例对象时可避免不必要的实例化减少开销并提升效率。 单线程版本 在懒汉模式下实例的创建时机是在第一次被使用时而不是在程序启动时。 如果程序启动后立即需要使用实例那么懒汉模式和饿汉模式的效果相似。 然而如果程序运行了较长时间仍未使用该实例懒汉模式会延迟实例的创建从而减少不必要的开销。 多线程版本 单例模式产生线程安全的原因 饿汉模式 懒汉模式 为什么会有单线程版本和多线程版本的懒汉模式写法呢我们来看单线程版本如果运用到多线程的环境下会出现什么问题 在懒汉模式中instance被声明为static因此多个线程调用getInstance()时返回的是同一个实例。 然而getInstance()方法中既包含读操作检查instance是否为null也包含写操作实例化instance。 尽管赋值操作本身是原子的但整个getInstance()方法并非原子操作。这意味着在多线程环境下判断和赋值操作不能保证紧密执行从而导致线程安全问题。 在多线程环境下若两个线程如 t1 和 t2同时执行 getInstance() 方法可能会导致值覆盖问题。 如上图t2 线程的赋值操作可能会覆盖 t1 线程新创建的对象导致第一个线程创建的对象被垃圾回收GC。 这不仅增加了不必要的开销还违背了单例模式的核心目标避免重复创建实例减少耗时操作节省资源。即使第一个对象很快被释放其创建过程中的数据加载依然会产生额外开销。 总结 饿汉模式仅涉及对实例的读操作不涉及写操作因此天然线程安全。无论在单线程还是多线程环境下其基本形式保持不变。懒汉模式在getInstance()中包含紧密相关的读写操作检查实例是否存在并创建实例但这些操作无法紧密执行导致线程安全问题。 解决单例模式的线程安全问题 面试题 这两个单例模式的 getInstance() 在多线程环境下调用是否会出现 bug如何解决 bug? 1. 通过加锁让读写操作紧密执行 饿汉模式本身不存在线程安全问题因为它仅涉及读操作不涉及写操作。 然而懒汉模式在多线程环境下可能出现线程安全问题原因在于getInstance()方法中的读写操作判断 赋值不能紧密执行。 为解决这一问题需要对相关操作进行加锁以确保线程安全。 方法一对方法中的读操作加锁 这样加锁后如果 t1 和 t2 还出现下图读写逻辑的执行顺序 t2 会阻塞等待 t1或 t1 等待 t2完成对象的创建读写操作结束后释放锁后第二个线程才能继续执行。此时第二个线程发现 instance 已非 null会直接返回已创建的实例不再重复创建。 方法二对整个方法加锁 直接对getInstance()方法加锁也能确保读写操作紧密执行。此时锁对象为SingletonLazy.class。这两种方法的效果相同 2. 处理加锁引入的新问题 问题描述 对于当前懒汉模式的代码多个线程共享一把锁不会导致死锁。只需确保第一个线程调用getInstance()时读写操作紧密执行即可。 后续线程在读取时发现instance ! null就不会触发写操作从而自然保证了线程安全。 然而若每次调用getInstance()方法时都进行加锁解锁操作由于synchronized是重量级锁多次加锁尤其是重量级锁会导致显著的性能开销从而降低程序效率。 拓展 StringBuffer 就是为了解决大量拼接字符串时产生很多中间对象问题而提供的一个类提供 append 和 insert 方法可以将字符串添加到已有序列的 末尾 或 指定位置。 StringBuffer 的本质是一个线程安全的可修改的字符序列把所有修改数据的方法都加上了synchronized。但是保证了线程安全是需要性能的代价的。 在很多情况下我们的字符串拼接操作不需要线程安全这时候 StringBuilder 登场了 StringBuilder 是 JDK1.5 发布的 StringBuilder 和 StringBuffer 本质上没什么区别就是去掉了保证线程安全的那部分减少了开销。所以在单线程情况下优先考虑使用 StringBuilder。 StringBuffer 和 StringBuilder 二者都继承了 AbstractStringBuilder底层都是利用可修改的 char数组 (JDK9以后是 byte 数组)。 所以如果我们有大量的字符串拼接如果能预知大小的话最好在new StringBuffer 或者 new StringBuilder 的时候设置好 capacity 避免多次扩容的开销扩容要抛弃原有数组还要进行数组拷贝创建新的数组。 解决方法 再嵌套一次判断操作既可以保证线程安全又可以避免大量加锁解锁产生的开销 在单线程环境下嵌套两层相同的if语句并无意义因为单线程只有一个执行流嵌套与否结果相同。但在多线程环境下多个并发执行流可能导致不同线程在执行判断操作时因其他线程修改了instance而得到不同结果。 例如在懒汉模式下即使两个if语句形式相同其目的和作用却不同 第一个if用于判断是否需要加锁第二个if用于判断是否需要创建对象。 这种结构虽看似巧合但实则必要。 3. 引入 volatile 关键字 问题描述 在懒汉模式的单例实现中使用volatile关键字修饰instance至关重要。以下是懒汉模式的单例实现代码 private static SingletonLazy instance null;public static SingletonLazy getInstance() {if (instance null) {synchronized (SingletonLazy.class) {if (instance null) {instance new SingletonLazy();}}}return instance; }如果不使用volatile修饰instance可能会出现以下问题 内存可见性问题 核心问题 在没有 volatile 修饰时线程 t1 对 instance 的写入可能仅停留在线程本地缓存CPU缓存或寄存器而非立即同步到主内存。此时线程 t2 读取的可能是自己缓存中的旧值null即使 t1 已完成初始化。即使 t2 进入同步块第一次判空if (instance null仍可能读取到未更新的缓存值导致不必要的锁竞争。第二次判空if (instance nullt2可能会错误地认为instance null并再次执行实例化逻辑导致又重复创建了新的实例。 内存可见性底层分析 硬件层面的原因 存储层级读写速度存储大小特性寄存器最快最小几十字节CPU直接计算使用的临时存储CPU缓存 (L1/L2/L3)快较小KB~MB级每个CPU核心/多核共享减少访问主存延迟主内存 (RAM)慢大GB级所有线程共享但访问速度比缓存慢100倍以上 速度差异CPU为了避免等待慢速的主内存读写会优先使用缓存和寄存器如将instance的值缓存在核心的L1缓存中。副作用线程t1修改instance后可能仅更新了当前核心的缓存而其他核心的缓存或主内存未被同步导致t2读取到过期数据。 Java内存模型JMM的抽象 硬件差异被JMM抽象为 工作内存线程私有和 主内存共享的分离工作内存包含CPU寄存器、缓存等线程私有的临时存储。主内存所有线程共享的真实内存。 问题本质 当线程t1未强制同步如缺少volatile或锁时JVM/CPU可能延迟将工作内存的修改刷回主内存其他线程也无法感知变更。 指令重排序 指令重排序的具体问题 instance new SingletonLazy() 的实际操作可分为以下步骤可能被JVM/CPU重排序 1. 分配对象内存空间堆上分配此时内存内容为默认值0/null 2. 调用构造函数初始化对象字段 3. 将引用赋值给 instance 变量此时 instance ! null可能的危险重排序 JVM可能将步骤 3赋值 和 2构造 调换顺序导致 1. 分配内存 2. 赋值给 instance此时 instance ! null但对象未初始化 3. 执行构造函数这就是指令重排序问题。 多线程场景下指令重排序的后果 线程 t1 执行 getInstance() 时发生重排序 先执行步骤1和3instance 已不为 null但对象未构造完成。 线程 t2 调用 getInstance() 第一次判空 if (instance null) 会跳过若 t2 立刻调用 instance.func()会访问未初始化的字段导致 空指针异常如果 func() 访问未初始化的引用字段。数据不一致如果 func() 依赖构造函数中初始化的值。 解决方法 使用volatile修饰instance后不仅能确保每次读取操作都直接从内存中读取还能防止与该变量相关的读取和修改操作发生重排序。 private volatile static SingletonLazy instance;public static SingletonLazy getInstance() {if (instance null) { // 第一次无锁检查synchronized (locker) { // 同步块if (instance null) { // 第二次检查instance new SingletonLazy(); // 受volatile保护}}}return instance; }volatile 是怎么解决内存可见性问题的呢? 通过内存屏障Memory Barrier直接操作硬件层 写操作强制将当前核心的缓存行Cache Line写回主内存并失效其他核心的缓存。读操作强制从主内存重新加载数据跳过缓存。 private static volatile SingletonLazy instance; // 通过volatile禁止缓存优化总结 直接原因CPU缓存和寄存器的速度优化导致可见性问题。根本原因硬件架构与编程语言内存模型的设计差异JMM需在性能与正确性间权衡。解决方案volatile通过内存屏障强制同步硬件层和JMM的约定。 总结为什么双重检查锁DCL必须用volatile 可见性确保t1的初始化结果对t2立即可见。禁止指令重排序 instance new SingletonLazy() 的字节码可能被重排序为 分配内存空间将引用写入instance此时instance ! null但对象未初始化执行构造函数 volatile会禁止这种重排序保证步骤2在3之后执行。 4. 指令重排序问题 模拟编译器指令重排序情景 要在超市中买到左边购物清单的物品有两种买法 方法一根据购物清单的顺序买(按照程序员编写的代码顺序进行编译) 方法二根据物品最近距离购买通过指令重排序后再编译 两种方法都能买到购物清单的所有物品但是比起第一种方法第二种方法在不改变原有逻辑的情况下优化执行指令顺序更高效地执行完所有的指令。 指令重排序概述 指令重排序的定义 指令重排序是指编译器或处理器为了提高性能在不改变程序执行结果的前提下对指令序列进行重新排序的优化技术。这种技术可以让计算机在执行指令时更高效地利用计算资源从而提高程序的执行效率。 指令重排序的类型 编译器重排序 编译器在生成目标代码时会对源代码中的指令进行优化和重排以提高程序的执行效率。这一过程在编译阶段完成目的是生成更高效的机器代码。 处理器重排序 处理器在执行指令时也可以对指令进行重排序以最大程度地利用处理器的流水线和多核等特性从而提高指令的执行效率。 指令重排序引发的问题 尽管指令重排序可以提高程序的执行效率但在多线程编程中可能会引发内存可见性问题。由于指令重排序可能导致共享变量的读写顺序与代码中的顺序不一致当多个线程同时访问共享变量时可能会出现数据不一致的情况。 指令重排序解决方案 为了解决指令重排序带来的问题可以采取以下措施 编译器层面通过禁止特定类型的编译器重排序确保指令的执行顺序符合预期。处理器层面通过插入内存屏障Memory Barrier来禁止特定类型的处理器重排序。内存屏障是一种CPU指令用来禁止处理器指令发生重排序从而保障指令执行的有序性。此外内存屏障还会在处理器写入或读取值之前将主内存的值写入高速缓存并清空无效队列从而保障变量的可见性。
http://www.zqtcl.cn/news/476220/

相关文章:

  • 蓝奏云注册网站工程设计方案主要内容
  • 建设官方网站企业网站公司可以做网站
  • 网站销售流程中装建设集团官网
  • 动易网站无法安装网站开发广告
  • 做网站类型注册域名com和cn
  • 织梦 做网站 知乎系统优化软件推荐
  • 长沙网站制作哪家强网站后台是怎么做的
  • Linux网站开发设计做ppt网站动态
  • 西部中大建设集团网站微商代理网
  • 做网站的参考文献有哪些火车头采集 wordpress
  • 网站不备案会有什么影响最新企业名录搜索软件
  • 邯郸做网站公司哪家好优化设计四年级下册数学答案
  • wordpress企业建站模版wordpress门户网站模板
  • 网站建设时间及简介企业注册代理
  • 网站首页制作方案wordpress中常用插件安装包
  • 阿里云建立网站赤坎网站建设公司
  • 时光轴 网站小公司做网站赚钱吗
  • 手机管理网站模板乐山住房和城乡建设厅网站
  • wordpress链接样式设置方法网络seo推广培训
  • 建站系统wordpress下载企业网站建设课程体会
  • 网站资源规划怎么写wordpress怎么解绑域名
  • 建湖企业做网站多少钱网页开发工具软件
  • WordPress怎么建小站wordpress替换谷歌字体库
  • ps建设网站步骤佛山做外贸网站特色
  • 杭州做代发的网站有哪些计算机基础网站建设和网络安全
  • 做汽配外贸是在哪个网站做山东百度推广
  • 网站类型大全cms监控软件下载官网
  • 网站设计制作 建网站免费asp地方门户网站系统
  • 凡科网做的网站保存后就上传了吗东莞网站推广建设
  • 网站推广案例闲鱼上做网站