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

新乡手机网站建设哪家专业/seo软文代写

新乡手机网站建设哪家专业,seo软文代写,涟源网站建设,保定风泉网络科技有限公司内存模型与高效并发 一、java 内存模型 【java 内存模型】是 Java Memory Model(JMM) 简单的说,JMM 定义了一套在多线程读写共享数据时(成员变量、数组)时,对数据的可见性、有序 性、和原子性的规则和保障…

内存模型与高效并发

一、java 内存模型

【java 内存模型】是 Java Memory Model(JMM)
简单的说,JMM 定义了一套在多线程读写共享数据时(成员变量、数组)时,对数据的可见性、有序
性、和原子性的规则和保障

1)原子性

原子性在学习线程时讲过,下面来个例子简单回顾一下:
问题提出,两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗?

2)问题分析

以上的结果可能是正数、负数、零。为什么呢?因为 Java 中对静态变量的自增,自减并不是原子操作。
在这里插入图片描述

3)解决方法

使用 synchronized(同步关键字)

synchronized( 对象 ) {要作为原子操作代码
}

注意:上例中 t1 和 t2 线程必须用 synchronized 锁住同一个 obj 对象,如果 t1 锁住的是 m1 对
象,t2 锁住的是 m2 对象,就好比两个人分别进入了两个不同的房间,没法起到同步的效果。

二、可见性

1)退不出的循环

一种现象,main 线程对另一个线程 t 中的变量的修改不可见。
在这里插入图片描述

在这里插入图片描述
由于t 线程需要反复调用 run 变量,JIT 会把 run 变量放在 工作内存中的高速缓存中,不需要从总内存中读取。
在这里插入图片描述
所以即使更改主内存中的 run 变量,也无法改变高速缓存中的 run 变量, t 线程会一直运行。

2)解决方法

volatile(易变关键字)。一般避免使用 volatile,因为不能保证线程的安全。而使用 synchronized 关键字既可以保证线程的可见性又可以保证线程的原子性。

它可以用来修饰成员变量和静态成员变量,他可以避免线程从自己的工作缓存中查找变量的值,必须到
主存中获取它的值,线程操作 volatile 变量都是直接操作主存

3)可见性

volatile 只是保证多线程之间的可见性,不保证原子性,即不保证多线程安全性。仅用在一个写线程,多个读线程的情况

synchronized 语句块既可以保证代码块的原子性,也同时保证代码块内变量的可见性。但缺点是 synchronized 是属于重量级操作,性能相对更低。

如果在前面示例的死循环中加入 System.out.println() 会发现即使不加 volatile 修饰符,线程 t 也能正确看到对 run 变量的修改了,因为 println() 方法底层 使用了 synchronized 关键字,使用 synchronized 关键字会清理缓存。

三、有序性

1)诡异的结果

int num = 0;
boolean ready = false;
// 线程1 执行此方法
public void actor1(I_Result r) {if(ready) {r.r1 = num + num;} else {r.r1 = 1;}
}
// 线程2 执行此方法
public void actor2(I_Result r) {num = 2;ready = true;
}

情况1:线程1 先执行,这时 ready = false,所以进入 else 分支结果为 1

情况2:线程2 先执行 num = 2,但没来得及执行 ready = true,线程1 执行,还是进入 else 分支,结果为1

情况3:线程2 执行到 ready = true,线程1 执行,这回进入 if 分支,结果为 4(因为 num 已经执行过了)

结果还有可能是 0。

这种情况下是:线程2 执行 ready = true,切换到线程1,进入 if 分支,相加为 0,再切回线程2 执行num = 2。

这种现象叫做指令重排,是 JIT 编译器在运行时的一些优化,这个现象需要通过大量测试才能复现

2)解决方法

volatile 修饰的变量,可以禁用指令重排

3)有序性理解

JVM 在不影响正确性的前提下,可以调整语句的执行顺序。这种特性称之为【指令重排】,多线程下【指令重排】会影响正确性,例如著名的 double-checked locking 模式实现单例。

public final class Singleton {private Singleton() { }private static Singleton INSTANCE = null;public static Singleton getInstance() {// 实例没创建,才会进入内部的 synchronized代码块if (INSTANCE == null) {synchronized (Singleton.class) {// 也许有其它线程已经创建实例,所以再判断一次if (INSTANCE == null) {INSTANCE = new Singleton();}}}return INSTANCE;}
}

以上的实现特点是:
懒惰实例化
首次使用 getInstance() 才使用 synchronized 加锁,后续使用时无需加锁

但在多线程环境下,上面的代码是有问题的, 如果有两个线程,一个线程为 INSTANCE 分配了空间,INSTANCE != null,但还未进行初始化操作,另一个线程在 INSTANCE != null时,直接返回了未初始化完成的单例。

对 INSTANCE 使用 volatile 修饰即可,可以禁用指令重排,但要注意在 JDK 5 以上的版本的 volatile 才
会真正有效

4)happens-before

happens-before 规定了哪些写操作对其它线程的读操作可见,它是可见性与有序性的一套规则总结,
抛开以下 happens-before 规则,JMM 并不能保证一个线程对共享变量的写,对于其它线程对该共享变
量的读可见

  • 线程解锁 m 之前对变量的写,对于接下来对 m 加锁的其它线程对该变量的读可见
  • 线程对 volatile 变量的写,对接下来其它线程对该变量的读可见
  • 线程 start 前对变量的写,对该线程开始后对该变量的读可见
  • 线程结束前对变量的写,对其它线程得知它结束后的读可见(比如其它线程调用 t1.isAlive() 或 t1.join()等待它结束)
  • 线程 t1 打断 t2(interrupt)前对变量的写,对于其他线程得知 t2 被打断后对变量的读可见(通过t2.interrupted 或 t2.isInterrupted)
  • 对变量默认值(0,false,null)的写,对其它线程对该变量的读可见
  • 具有传递性,如果 x hb-> y 并且 y hb-> z 那么有 x hb-> z

四、CAS 与 原子类

1)CAS

CAS 即 Compare and Swap, 它体现的是一种乐观锁的思想,比如多个线程要对一个共享的整型变量执行 +1 操作:

// 需要不断尝试
while(true) {int 旧值 = 共享变量 ; // 比如拿到了当前值 0int 结果 = 旧值 + 1; // 在旧值 0 的基础上增加 1 ,正确结果是 1/*这时候如果别的线程把共享变量改成了 5,本线程的正确结果 1 就作废了,这时候compareAndSwap 返回 false,重新尝试,直到:compareAndSwap 返回 true,表示我本线程做修改的同时,别的线程没有干扰*/if( compareAndSwap ( 旧值, 结果 )) {// 成功,退出循环}
}

获取共享变量时,为了保证该变量的可见性,需要使用 volatile 修饰。结合 CAS 和 volatile 可以实现无
锁并发,适用于竞争不激烈、多核 CPU 的场景下。

  • 因为没有使用 synchronized,所以线程不会陷入阻塞,这是效率提升的因素之一
  • 但如果竞争激烈,可以想到重试必然频繁发生,反而效率会受影响

CAS 底层依赖于一个 Unsafe 类来直接调用操作系统底层的 CAS 指令。

2)乐观锁与悲观锁

  • CAS 是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量,就算改了也没关系,我吃亏点再重试呗。
  • synchronized 是基于悲观锁的思想:最悲观的估计,得防着其它线程来修改共享变量,我上了锁
    你们都别想改,我改完了解开锁,你们才有机会。

3)原子操作类

juc(java.util.concurrent)中提供了原子操作类,可以提供线程安全的操作,例如:AtomicInteger、
AtomicBoolean等,它们底层就是采用 CAS 技术 + volatile 来实现的。

五、synchronized 优化

synchronized 是一个重量级锁,如果要阻塞或唤醒一条线程,则需要操作系统来帮忙完成,这就不可避免的陷入用户态到内核态的转换中,进行这种转换需要耗费很多的处理器时间,状态转换消耗的时间甚至会比用户代码本身执行的时间还要长。

但 synchronized有非常大的优化余地,JDK 6 之后synchronized synchronized与ReentrantLock的性能基本上能够持平。

Java HotSpot 虚拟机中,每个对象都有对象头(包括 class 指针和 Mark Word)。Mark Word 平时存
储这个对象的 哈希码 、 分代年龄 ,当加锁时,这些信息就根据情况被替换为 标记位 、 线程锁记录指
针 、 重量级锁指针 、 线程ID 等内容

1)轻量级锁

如果一个对象虽然有多线程访问,但多线程访问的时间是错开的(也就是没有竞争),那么可以使用轻量级锁来优化。

每个线程都的栈帧都会包含一个锁记录的结构,内部可以存储锁定对象的 Mark Word

在这里插入图片描述
轻量级锁的解锁过程是通过CAS操作来进行的。
如果出现两条以上的线程争用同一个锁的情况,那轻量级锁就不再有效,必须要膨胀为重量级锁,锁标志
的状态值变为“10”,此时Mark Word中存储的就是指向重量级锁(互斥量)的指针,后面等待锁的线程也必须进入阻塞状态。

2)锁膨胀

如果在尝试加轻量级锁的过程中,CAS 操作无法成功,这时一种情况就是有其它线程为此对象加上了轻
量级锁(有竞争),这时需要进行锁膨胀,将轻量级锁变为重量级锁。

3)重量级锁

重量级锁竞争的时候,还可以使用自旋来进行优化,如果当前线程自旋成功(即这时候持锁线程已经退
出了同步块,释放了锁),这时当前线程就可以避免阻塞。

在 Java 6 之后自旋锁是自适应的,比如对象刚刚的一次自旋操作成功过,那么认为这次自旋成功的可能
性会高,就多自旋几次;反之,就少自旋甚至不自旋,总之,比较智能。

  • 自旋会占用 CPU 时间,单核 CPU 自旋就是浪费,多核 CPU 自旋才能发挥优势。
  • 好比等红灯时汽车是不是熄火,不熄火相当于自旋(等待时间短了划算),熄火了相当于阻塞(等
    待时间长了划算)
  • Java 7 之后不能控制是否开启自旋功能

4)偏向锁

轻量级锁在没有竞争时(就自己这个线程),每次重入仍然需要执行 CAS 操作。
Java 6 中引入了偏向锁来做进一步优化:只有第一次使用 CAS 将线程 ID 设置到对象的 Mark Word 头,之后发现这个线程 ID是自己的就表示没有竞争,不用重新 CAS。

偏向锁中的“偏”,就是偏心的“偏”、偏袒的“偏”。它的意思是这个锁会偏向于第一个获得它的线
程,如果在接下来的执行过程中,该锁一直没有被其他的线程获取,则持有偏向锁的线程将永远不需
要再进行同步。

偏向锁可以提高带有同步但无竞争的程序性能,但它同样是一个带有效益权衡(Trade Off)性质的优化,也就是说它并非总是对程序运行有利。如果程序中大多数的锁都总是被多个不同的线程访问,那偏向模式就是多余的。在具体问题具体分析的前提下,有时候使用参数-XX:-UseBiasedLocking来禁止偏向锁优化反而可以提升性能。

5)其他优化

1.减少上锁时间

同步代码块中尽量短

2.减少锁的粒度

将一个锁拆分为多个锁提高并发度,例如:

  • ConcurrentHashMap
  • LongAdder 分为 base 和 cells 两部分。没有并发争用的时候或者是 cells 数组正在初始化的时候,会使用 CAS 来累加值到 base,有并发争用,会初始化 cells 数组,数组有多少个 cell,就允许有多少线程并行修改,最后将数组中每个 cell 累加,再加上 base 就是最终的值
  • LinkedBlockingQueue 入队和出队使用不同的锁,相对于LinkedBlockingArray只有一个锁效率要高
3. 锁粗化

多次循环进入同步代码块不如同步块内多次循环
另外 JVM 可能会做如下优化,把多次 append 的加锁操作粗化为一次,(因为都是对同一个对象加锁,
没必要重入多次)

new StringBuffer().append("a").append("b").append("c");
4. 锁消除

JVM 会进行代码的逃逸分析,例如某个加锁对象是方法内局部变量,不会被其它线程所访问到,这时候
就会被即时编译器忽略掉所有同步操作。

5. 读写分离

CopyOnWriteArrayList
ConyOnWriteSet

参考:
https://wiki.openjdk.java.net/display/HotSpot/Synchronization

http://luojinping.com/2015/07/09/java锁优化/

https://www.infoq.cn/article/java-se-16-synchronized

https://www.jianshu.com/p/9932047a89be

https://www.cnblogs.com/sheeva/p/6366782.html

https://stackoverflow.com/questions/46312817/does-java-ever-rebias-an-individual-lock

相关文章:

JVM(六)——内存模型与高效并发

内存模型与高效并发 一、java 内存模型 【java 内存模型】是 Java Memory Model(JMM) 简单的说,JMM 定义了一套在多线程读写共享数据时(成员变量、数组)时,对数据的可见性、有序 性、和原子性的规则和保障…...

C++:关键字(4)

在c中的关键字就是我们各个写的各种代码 这些就是关键字,这些东西是无法当参数的,比如在给变量名设置为int那就不行 这就是个错的 在写其他的参数时候,不可以使用关键词作为参数...

STM32串口收发单字节数据原理及程序实现

线路连接: 显示屏的SCA接在B11,SCL接在B10,串口的RX连接A9,TX连接A10。 程序编写: 在上一个博客中实现了串口的发送代码,这里实现串口的接收代码,在上一个代码的基础上增加程序功能。 Seiral.…...

openGauss + Datakit搭建openGauss运维平台

系统架构OS 硬件需求:2c4g [rootlocalhost ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [rootlocalhost ~]# uname -m x86_64 [rootlocalhost ~]# hostname -I 192.168.92.32 下载地址:https://opengauss.org/zh/download/ 下载…...

【疑惑】-谷歌是如何获取数据的

搜索引擎爬虫: 谷歌的搜索引擎通过爬虫程序在互联网上爬取和收集网页信息。这些爬虫会遵循特点的算法和规则,访问内容,并且提取出关键信息 用户的搜索行为: 当用户使用谷歌搜索引擎进行搜索的时候,谷歌会收集分析用户…...

Java static和继承

static特点 Java中的static关键字允许在没有创建类的实例的情况下进行调用。以下是static关键字的主要用途和特点: 静态变量(类变量):使用static关键字声明的变量称为静态变量或类变量。这些变量属于类本身,而不是类…...

亲身体验!人工智能对话无障碍 —— BRClient 使用指南

01 概述 BRClient 这个名字来源于“Bedrock Client”的简称,寓意是为用户提供一个坚实的基础。BRClient 作为一个开源的桌面应用,为用户提供了友好的图形界面,让每个人都能够轻松访问和使用 Claude 3 的强大功能。用户可以自定义 Claude 3 的…...

【数据库管理操作】Mysql 创建学生数据库及对数据表进行修改

MySQL 创建学生成绩数据库 1.创建数据库 create database studentscore;创建完成之后,如果需要使用该数据,使用use命令 use studentscore;创建表前查看当前数据库中包含的表 show tables; 2.创建bclass表 create table bclass( class_id char(8) …...

vue2 export default写法,computed、methods的使用

<template><div><h2>{{nameAll}}</h2><h2>{{method}}</h2><h2>{{tt()}}</h2><h2>{{firstName}}</h2><h2>更新后赋值数据&#xff1a;{{lastName}}</h2><h2>赋值数据:{{writeValue}}</h2>…...

负氧离子监测站:创造健康生活环境

TH-FZ5在蓝天白云之下&#xff0c;那一座座高耸的全彩屏负氧离子监测站&#xff0c;如同一支支科技的绿芽&#xff0c;静静破土而出&#xff0c;为这片土地带来了新的生命力。这些现代化的设备不仅美化了环境&#xff0c;更是我们呼吸健康守护者&#xff0c;它们的存在让我们的…...

【jvm】young gc full gc

何时触发YoungGC或FullGC YoungGC的触发时常在发生&#xff0c;当新生代的Eden区满了之后就会触发YoungGC。 FullGC在多个情况下都会被触发&#xff1a; 1、发生Young GC之前进行检查&#xff0c;如果“老年代可用的连续内存空间” < “新生代历次Young GC后升入老年代的对象…...

2024年腾讯云服务器租用价格_轻量和CVM报价

腾讯云服务器价格表2024年最新价格&#xff0c;轻量2核2G3M服务器61元一年、2核2G4M服务器99元1年&#xff0c;三年560元、2核4G5M服务器165元一年、3年900元、轻量4核8M12M服务器646元15个月、4核16G10M配置32元1个月、8核32G配置115元1个月&#xff0c;345元3个月。CVM云服务…...

【go从入门到精通】for循环控制

作者简介&#xff1a; 高科&#xff0c;先后在 IBM PlatformComputing从事网格计算&#xff0c;淘米网&#xff0c;网易从事游戏服务器开发&#xff0c;拥有丰富的C&#xff0c;go等语言开发经验&#xff0c;mysql&#xff0c;mongo&#xff0c;redis等数据库&#xff0c;设计模…...

<chrono>, clock_gettime(), gettimeofday()对比

精度&#xff08;Precision&#xff09;&#xff1a; <chrono>: 提供了纳秒级别的精度&#xff0c;可以满足大多数应用的需求。clock_gettime(): 提供了纳秒级别的精度&#xff0c;与 <chrono> 相当。gettimeofday(): 提供了微秒级别的精度&#xff0c;相对于前两者…...

基于 YAML 接口自动化测试框架设计

在设计自动化测试框架的时候&#xff0c;我们会经常将测试数据保存在外部的文件&#xff08;如Excel、YAML、CSV&#xff09;&#xff0c;或者数据库中&#xff0c;实现脚本与数据解耦&#xff0c;方便后期维护。目前非常多的自动化测试框架采用通过Excel或者YAML文件直接编写测…...

团体程序设计天梯赛 L2-031 深入虎穴

L2-3深入虎穴 分数 25 名的王牌间谍 007 需要执行一次任务&#xff0c;获取敌方的机密情报。已知情报藏在一个地下迷宫里&#xff0c;迷宫只有一个入口&#xff0c;里面有很多条通路&#xff0c;每条路通向一扇门。每一扇门背后或者是一个房间&#xff0c;或者又有很多条路&a…...

基于Givens旋转完成QR分解进而求解实矩阵的逆矩阵

基于Givens旋转完成QR分解进而求解实矩阵的逆矩阵 目录 前言 一、Givens旋转简介 二、Givens旋转解释 三、Givens旋转进行QR分解 四、Givens旋转进行QR分解数值计算例子 五、求逆矩阵 六、MATLAB仿真 七、参考资料 总结 前言 在进行QR分解时&#xff0c;HouseHolder变换…...

学习使用xbox手柄控制小乌龟节点移动

使用xbox手柄控制小乌龟&#xff0c;首先要下载joy功能包&#xff0c;发布sensor_msgs话题也就是手柄和ros通信的话题。 下载的步骤就根据官方文档即可 joy/Tutorials/ConfiguringALinuxJoystick - ROS Wiki 这里我提供一下具体步骤 第一步 安装joy 首先安装对应系统版本的…...

OpenLayers6实战,OpenLayers绘制特殊图形,OpenLayers绘制四角形(菱形),OpenLayers绘制菱形

专栏目录: OpenLayers实战进阶专栏目录 前言 本章讲解如何使用OpenLayers6实现绘制特殊图形,以绘制四角形(菱形),OpenLayers绘制菱形的功能为例。 本章核心代码不依赖任何第三方插件,只依赖OpenLayers。 需要注意的是两个操作按钮需要引入ElementUI 二、依赖和使用 &q…...

虚拟机如何在原有磁盘上扩容

虚拟机未开启状态–菜单栏–虚拟机–快照–拍摄快照–拍摄快照– 菜单栏–虚拟机–快照–快照管理器–点击刚刚的快照1–删除–是– 文件–新建或者打开–硬盘&#xff08;以本人Win 10.64.3GL为例&#xff09;–虚拟机设置–硬件– 硬盘&#xff08;SATA&#xff09;–磁盘实…...

2024-03-27 作业

作业要求&#xff1a; 整理课上代码整理思维导图完成下面类 作业1&#xff1a; 完成了 作业2&#xff1a; 作业3&#xff1a; class myString {private:char *str; //记录c风格的字符串int size; //记录字符串的实际长度public://无参构造myString():si…...

C语言二叉树和堆(个人笔记)

二叉树和堆 二叉树1二叉树的概念和结构1.1特殊的二叉树1.2二叉树的性质&#xff08;规定根节点的层数为1&#xff09;1.3二叉树的存储结构 2.二叉树的顺序结构和实现2.1二叉树的顺序结构2.2堆的概念和结构2.3堆的实现2.4堆的应用2.4.1堆排序 2.5TOP-K问题 3.二叉树的遍历4.二叉…...

重学SpringBoot3-Profiles介绍

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-Profiles介绍 Profiles简介如何在Spring Boot中使用Profiles定义Profiles激活ProfilesIDEA设置active profile使用Profile-specific配置文件 条件化Bean…...

Transformer 论文阅读笔记

文章目录 前言论文阅读研究现状工作内容模型架构训练过程实验结果模型代码 其他评价 前言 Transformer可以说是深度学习领域最重要的&#xff0c;里程碑式的工作之一&#xff0c;发表于2017年的NIPS。该模型开创了自MLP&#xff08;多层感知机&#xff09;、CNN&#xff08;卷…...

Vue 3中ref和reactive的区别

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…...

oracle19c adg搭建

一、环境搭建 主机IPora19192.168.232.111ora19std192.168.232.112 本文结合&#xff1a;https://blog.csdn.net/weixin_63131036/article/details/136635553 1.配置网络yum源 1.删除redhat7.0系统自带的yum软件包&#xff1b; rpm -qa|grep yum >oldyum.pkg 备份原信息 …...

关闭Elasticsearch built-in security features are not enabled

禁用Kibana安全提示&#xff08;Elasticsearch built-in security features are not enabled&#xff09; Kibana提示#! Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.e…...

MC0248 密码判断器(判断强弱密码)

原题链接<---- islower 小写字母判断 isupper 大写字母判断 isdigit 数字判断 题目: 小码哥在是一位密码领域的初学者&#xff0c;有一天他的老师给他了一串密码&#xff0c;要他判断这个密码是否是强密码&#xff0c;老师和他说强密码就是需要同时达到以下要求&#xff1…...

vue3+threejs新手从零开发卡牌游戏(十六):初始化对方手牌

添加对方手牌区时注意位置调整&#xff0c;以及手牌应该是背面朝上&#xff0c;加个rotateX翻转即可&#xff0c;其他代码和p1.vue代码一致&#xff0c;game/hand/p2.vue代码如下&#xff1a; <template><div></div> </template><script setup lan…...

网页无插件视频播放器,支持录像、截图、音视频播放,多路播放等,提供源码下载

前言 本播放器内部采用jessibuca插件接口&#xff0c;支持录像、截图、音视频播放等功能。播放器播放基于ws流&#xff0c;分屏操作支持1分屏、4分屏、6分屏、9分屏方式。 jessibuca工作原理是通过Emscripten将音视频解码库编译成Js&#xff08;WebAssembly&#xff0c;简称was…...