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

郑州网站推广报价做淘宝优惠券网站要多少钱

郑州网站推广报价,做淘宝优惠券网站要多少钱,网建公司,个人备案放企业网站1. 概述JMM 即 Java Memory Model,它定义了主存(静态变量,成员变量等共享数据)、工作内存(指每个线程私有的数据)抽象概念,它们底层运作是非常复杂的,需要使用CPU寄存器、缓存、硬件…

1. 概述

JMM Java Memory Model,它定义了主存(静态变量,成员变量等共享数据)、工作内存(指每个线程私有的数据)抽象概念,它们底层运作是非常复杂的,需要使用CPU寄存器、缓存、硬件内存、CPU指令优化等。(synchronized、volatile等等)
JMM是 Java 语言规范中定义的一套抽象规则和机制,用于规定多线程环境下线程如何以及何时能够看到其他线程对共享变量的修改
就是计算机底层太复杂了,Java提供了关键字等来帮助我们控制,比如是不是要用缓存啊、是不是要指令优化啊等等,屏蔽了我们和操作系统之间的直接操作
JMM体现在以下几个方面:
  • 原子性 - 保证指令不会受到线程上下文切换的影响
  • 可见性 - 保证指令不会受到cpu缓存的影响
  • 有序性 - 保证指令不会收到cpu指令并行优化的影响

一句话概括:JMM 是 Java 为多线程程序建立的“游戏规则”,它告诉开发者在什么情况下,一个线程对共享变量的修改能被另一个线程看到,从而避免因硬件和编译器优化导致的诡异 bug。

2. 可见性

static boolean run = true;
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(()->{while(run){// ....}});t.start();sleep(1);run = false; // 线程t不会如预想的停下来
}
t 线程要频繁从主内存中读取 run 的值,JIT 编译器会将 run 的值缓存至自己工作内存中的高速缓存中,减少对主存中 run 的访问,提高效率。
1 秒之后,main 线程修改了 run 的值,并同步至主存,而 t 是从自己工作内存中的高速缓存中读取这个变量 的值,结果永远是旧值
解决方法
volatile(易变关键字)
它可以用来修饰成员变量和静态成员变量,他可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值,线程操作 volatile 变量都是直接操作主存
synchronized既可以保证原子性也可以保证可见性,但是synchronized的基于Monitor来实现的,比较重量级,而且volatile比较轻量,但只保证可见性,不保证原子性
  • System.out 是什么?

    • System.out 是一个 PrintStream 类型的静态变量,代表标准输出流。
    • println() 方法是 PrintStream 类的方法。
  • 为什么看起来是原子的?

    • PrintStream 类的大多数输出方法(包括 println)都被声明为 synchronized
    • 所以System.out.println();既保证了原子性,也保证了可见性

简单来说,多个线程访问同一个共享变量,一定要加上volatile,保证多线程的可见性,保证每个线程看到的都是最新的结果

3. 有序性

指令重排是JIT编译器在运行时的一些优化

在单线程中,指令重排不会影响正确性,但在多线程会影响正确性

现代CPU拥有多个执行单元(如整数运算单元、浮点运算单元、加载/存储单元等),可以同时执行多条不同的指令。

  • 问题:如果指令严格按照代码顺序执行,可能会出现“等待”情况。

现代CPU采用指令流水线技术,将一条指令的执行分为取指、译码、执行、访存、写回等多个阶段。理想情况下,每个时钟周期都能完成一条指令。

举个例子:

CPU也是同理,指令重排能提高并发度,也就是提供吞吐量

多线程下指令重排出现的问题:

I_Result是一个对象,有一个属性r1用来保存结果,问,有几种可能?

1或4或0(指令重排导致,先ready = true 再r.r1 = num+num再num = 2)

怎么避免指令重排现象?

在ready前面加上volatile关键字,能保证ready之前的代码都不会出现指令重排的现象,这是使用了写屏障技术

4. volatile实现原理

可见性的保证

有序性的保证

volatile的内存屏障技术,既保证可见性,又保证有序性

5. DCL(double-checked locking

synchronized保证有序性只是保证执行被修饰的临界区代码块多线程必须串行执行,但并不能禁止内部进行指令重排序.
且前提条件是: 必须将共享变量完全交给synchronized来管理,双重锁这里就是将共享变量暴露在了synchronized外了,再加上指令重排序,所产生的问题

这段代码的问题是,因为new这个操作不是原子性的,会导致指令重排现象,也就是说,t2拿到的INSTANCE对象可能只是一个半初始化对象,这个时候直接return是有问题的

在INSTANCE前面加上volatile,依然是使用内存屏障技术,可以避免指令重排现象

6. happens-before

happens-before 规定了对共享变量的写操作对其它线程的读操作可见,它是可见性与有序性的一套规则总结,抛开以下 happens-before 规则,JMM 并不能保证一个线程对共享变量的写,对于其它线程对该共享变量的读可见
  • 线程解锁 m 之前对变量的写,对于接下来对 m 加锁的其它线程对该变量的读可见
  • 线程对 volatile 变量的写,对接下来其它线程对该变量的读可见
  • 线程 start 前对变量的写,对该线程开始后对该变量的读可见
  • 线程结束前对变量的写,对其它线程得知它结束后的读可见(比如其它线程调用 t1.isAlive() t1.join()等待 它结束)
  • 线程 t1 打断 t2interrupt)前对变量的写,对于其他线程得知 t2 被打断后对变量的读可见(通过 t2.interrupted 或 t2.isInterrupted
  • 对变量默认值(0falsenull)的写,对其它线程对该变量的读可见
  • 具有传递性,如果 x hb-> y 并且 y hb-> z 那么有 x hb-> z ,配合 volatile 的防指令重排,有下面的例子:
volatile static int x;
static int y;
new Thread(()->{ y = 10;x = 20;
},"t1").start();
new Thread(()->{// x=20 对 t2 可见, 同时 y=10 也对 t2 可见// 因为volatile写屏障技术,不会把x之前的代码放到现在,既然你x都可见了,那么前面的y也可见System.out.println(x); 
},"t2").start();

7. 练习题

1. 单例模式

// 问题1:为什么加 final
// 问题2:如果实现了序列化接口, 还要做什么来防止反序列化破坏单例
public final class Singleton implements Serializable {// 问题3:为什么设置为私有? 是否能防止反射创建新的实例?private Singleton() {}// 问题4:这样初始化是否能保证单例对象创建时的线程安全?private static final Singleton INSTANCE = new Singleton();// 问题5:为什么提供静态方法而不是直接将 INSTANCE 设置为 public, 说出你知道的理由public static Singleton getInstance() {return INSTANCE;}public Object readResolve() {return INSTANCE;}
}
  • 问题1:不允许有子类继承它,重写修改它,保证了单例
  • 问题2:因为在反序列化的时候,会创建一个新的Singleton,这样就出现了两个Singleton,不是单例了,可以使用readResolve方法直接return,这样就不会创建一个新的了
  • 问题3:不能,可以暴力反射
  • 问题4:可以,因为有static变量,我们知道static变量是在类加载的时候赋值的,JVM会保证它的原子性
  • 问题5:使用方法会有更好的封装性,可以内部实现一些其他初始化操作,可以对创建单例时有更多的控制,定义泛型等

实现2

问题1: 枚举类里面其实就是静态成员变量
问题2: 不会,静态成员变量都是在类加载阶段完成的,由JVM保证线程安全
问题3: 枚举单例不能用反射来破坏单例
问题4: 也可以防反序列化破坏单例
问题5: 枚举也是静态成员变量.所以枚举也是饿汉式
问题6: 再写一些构造方法等等来写初始化的一些逻辑

实现3

静态内部类(类加载是懒惰性加载,只有调用到getInstance()时才会触发类加载内部类),在类加载时,JVM保证原子性

http://www.dtcms.com/a/439156.html

相关文章:

  • 网站建设推广 seoseo网站页面优化
  • 第7篇|场址适应性评估:把“课本里的风机”落到“具体那座山谷和海岸”
  • 网站建设找客户国外jquery特效网站
  • 《强化学习数学原理》学习笔记6——贝尔曼最优方程的压缩性质
  • linux 学习平台 arm+x86 搭建
  • 哪里的网站可以做围棋死活题黄江镇网站仿做
  • 制作网站结构设计国外服务器网站打开慢
  • 数据结构---栈和队列详解(下)
  • 湖南新能源公司中企动力网站建设wordpress网页静态化
  • Kubernetes从零入门(三):Kubernetes API--资源模型
  • 4Byte Instruction SSIC 8bitCPU
  • 可以做外链的网站适合中层管理的培训
  • LangChain源码分析(十)- Memory记忆管理
  • php怎么用来做网站东莞制作网站公司
  • 智能化背景下的SEO关键词策略创新与应用研究
  • AI(学习笔记第九课) 使用langchain的MultiQueryRetriever和indexing
  • Unity学习之寻路导航系统AI Navigation
  • 数据结构学习(1)——指针、结构体、链表(C语言)
  • 【LAMMPS】lammps施加电场或磁场
  • IO模型select与poll,epoll
  • 设计模式(C++)详解——状态模式(State)(2)
  • 网站开发包括几部分上海中学图片
  • 网站开发后台一般用什么计算机网站开发和软件开发
  • 商业网站图片网站建设公司如何营销
  • 深入理解文件系统和软硬链接
  • 【408计组】3.3 SRAM和DRAM
  • 山东菏泽建设银行网站上海有哪些做网站
  • 【开题答辩全过程】以 SpringMVC在筑原平面设计定制管理信息系统的应用与实践为例,包含答辩的问题和答案
  • 昂瑞微,凭啥?
  • 【数据结构】二叉树的遍历与操作