流程图
2023-11-08 17:42:24 0 举报
基礎知識流程圖
作者其他创作
大纲/内容
锁消除
失败
线程外改的变量,对于线程不可见
线程ID
修饰静态方法
01
ThreadA
OOM
成功
因为 L1、L2 缓存是独立的,所以就会导致可见性问题!!当多个线程并行执行一个共享数据时,都同时在本 cpu 的高速缓存中的时候,最新的数据对其他的 cpu 是不可见的!!
获取时间片
重量级锁
线程1
堆Heap
Java Messaging Service能够发送和接收信息
Spring SPI
Eden
锁优化技术
Node
Unsafe
是否偏向锁
提供了最基础Web支持,主要建立于核心容器之上,通过Servlet或者Listeners来 初始化IOC容器。
对象操作
掃描配置文件路徑下的需要的類封裝成BeanDefinition放到BeanDefinitionMap
锁标志位
创建线程运行线程
null
返回原始A
next
清空工作内存
spring-aspects
HandlerMapping
prev
开始
Old
重量级锁是一种称谓: synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的,监视器锁本身依赖底层的操作系统的 Mutex Lock来实现。操作系统实现线程的切换需要从用户态切换到核心态,成本非常高。这种依赖于操作系统 Mutex Lock来实现的锁称为重量级锁。为了优化synchonized,引入了轻量级锁,偏向锁。Java中的重量级锁: synchronized synchronized是Java中的关键字:用来修饰方法、对象实例。属于独占锁、悲观锁、可重入锁、非公平锁。1.作用于实例方法时,锁住的是对象的实例(this);2.当作用于静态方法时,锁住的是 Class类,相当于类的一个全局锁, 会锁所有调用该方法的线程;3.synchronized 作用于一个非 NULL的对象实例时,锁住的是所有以该对象为锁的代码块。它有多个队列,当多个线程一起访问某个对象监视器的时候,对象监视器会将这些线程存储在不同的容器中。每个对象都有个 monitor 对象, 加锁就是在竞争 monitor 对象,代码块加锁是在代码块前后分别加上 monitorenter 和 monitorexit 指令来实现的,方法加锁是通过一个标记位来判断的。
本地方法栈Native Method Stack
spring
broker
join规则
获得偏向锁Thread Id | epoch | gc分代年龄 | 是否偏向锁(1) | 锁标识(01)
2bit
锁标识(11)
对象头
运行操作
目前锁状态
系统调度yield
64位
写入Socket
类装载器
官网插件
挂起当前线程Mutex Lock(互斥锁)
Monitor监视锁
虚拟机栈VM Stack
借用Thread
10
true
0bit
主要是与Web前端的全双工通讯的协议。
有时间等待Thread.sleep(long)Object.wait(long)Thread.join(long)LockSupport.parkNanos(xx)LockSupport.arkUntil()
synchronized
偏向时间戳
非公平锁是一种思想: 线程尝试获取锁,如果获取不到,则再采用公平锁的方式。多个线程获取锁的顺序,不是按照先到先得的顺序,有可能后申请锁的线程比先申请的线程优先获取锁。优点: 非公平锁的性能高于公平锁。缺点: 有可能造成线程饥饿(某个线程很长一段时间获取不到锁)Java中的非公平锁:synchronized是非公平锁,ReentrantLock通过构造函数指定该锁是公平的还是非公平的,默认是非公平的。
Class相关
11
BLOCKED阻塞
spring-context-support
锁撤销状态
false
自旋锁
L2 Cache
判断Old区空间十分足够
CAS
硬件设备
升级重量级锁
CAS 操作替换Thread ID
唤醒原持有偏向锁的线程
CAS操作1&21.当前对象头的Mark Word中的锁记录指针指向是否仍然当前线程锁记录2.拷贝在原持有偏向锁线程的锁记录中的MarkWord和对象头中的MarkWord信息一致
独占锁
根据topic查询路由信息Producer
將對象A的工廠放入到三級緩存中
刪除標記
as-if-serial ,不管怎么重排序,单线程的程序的执行结果不能改变。•处理器不能对存在依赖关系的操作进行重排序,因为重排序会改变程序的执行结果。•对于没有依赖关系的指令,即便是重排序,也不会改变在单线程环境下的执行结果。
数组长度
可见性:一个线程对共享变量做了修改之后,其他的线程立即能够看到(感知到)该变量的这种修改(变化)。
P:Partition Tolerance(分区容错):系统应该能持续提供服务,即使系统内部有消息丢失(分区)
標記對象A
偏向锁状态标识(1) 是
2PC二阶段提交(Twophase Commit)
锁状态
NEWnew Thread()
偏向锁
指向互斥量(重量级锁)的指针
锁消除是一种优化技术: 就是把锁干掉。当Java虚拟机运行时发现有些共享数据不会被线程竞争时就可以进行锁消除。那如何判断共享数据不会被线程竞争?利用逃逸分析技术:分析对象的作用域,如果对象在A方法中定义后,被作为参数传递到B方法中,则称为方法逃逸;如果被其他线程访问,则称为线程逃逸。在堆上的某个数据不会逃逸出去被其他线程访问到,就可以把它当作栈上数据对待,认为它是线程私有的,同步加锁就不需要了。
锁状态标记
虚拟机hotspot对象在内存中的分布
Transaction Manager(TM)– 事务管理器 - 这是一个产品经理– 全局事务的发起员,能够根据全局事务的成功与否来对全局提交或回滚进行决策。
释放锁
spring-beans
spring-webflux
volatile 变量规则
屬性注入A對象
设置程序状态字PSW
开始轻量级锁解锁
方法区Method Area
springBoot-top
自旋锁是一种技术: 为了让线程等待,我们只须让线程执行一个忙循环(自旋)。现在绝大多数的个人电脑和服务器都是多路(核)处理器系统,如果物理机器有一个以上的处理器或者处理器核心,能让两个或以上的线程同时并行执行,就可以让后面请求锁的那个线程“稍等一会”,但不放弃处理器的执行时间,看看持有锁的线程是否很快就会释放锁。自旋锁的优点: 避免了线程切换的开销。挂起线程和恢复线程的操作都需要转入内核态中完成,这些操作给Java虚拟机的并发性能带来了很大的压力。自旋锁的缺点: 占用处理器的时间,如果占用的时间很长,会白白消耗处理器资源,而不会做任何有价值的工作,带来性能的浪费。因此自旋等待的时间必须有一定的限度,如果自旋超过了限定的次数仍然没有成功获得锁,就应当使用传统的方式去挂起线程。自旋次数默认值:10次,可以使用参数-XX:PreBlockSpin来自行更改。自适应自旋: 自适应意味着自旋的时间不再是固定的,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定的。有了自适应自旋,随着程序运行时间的增长及性能监控信息的不断完善,虚拟机对程序锁的状态预测就会越来越精准。Java中的自旋锁: CAS操作中的比较操作失败后的自旋等待。
确保线程互斥的访问同步代码保证共享变量的改变能够及时可见有效解决指令重排序问题
唤醒status--
原持有偏向锁线程的栈帧中分配锁记录(Lock Record)
共享锁
Base理论
从二级缓存中得到代理A对象替换原生A对象
同步锁与互斥锁同义,表示并发执行的多个线程,在同一时间内只允许一个线程访问共享数据。Java中的同步锁: synchronized
基于CAS
执行情况下
判断对象头中是否存储线程1
讀取配置文件
start规则
启用start方法-调用了底层的start0方法
創建原生的B對象
從三級緩存中通過工厰拿到A對象
运行操作系统程序,操作硬件
Bean工厂与Bean的装配
將B注入到原生A對象中
AService
由操作系统OS调度算法进行分配给cpu进行
Reentrantlock(true)
將對象B的工廠放到三級緩存中
对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
重量级锁状态标识(00)
SPI机制
Survivor区是否开启担保机制来减少full gc
ObjectMonitor实现
CAS操作将对象头中Mark Word的锁记录指向当前线程中的锁记录
將實例放到一級緩存,刪除二三級緩存中B對象
BASE 是对 CAP 中一致性和可用性权衡的结果,是基于 CAP 定律逐步演化而来。其核心思想是即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达最终一致性。
架构分层
重量级锁阻塞等待
普通对象创建
Enable模块驱动
解析器
启动一个定时任务,每次都会向NameServer注册自己,不断覆盖到NameServer存的Broker的信息,默认30s一次告诉NameServer当前broker处于活跃状态
可见性问题
锁
内存操作
新对象创建成功
synchronized
HandlerAdapter
unused
Thread
JDK SPI
是(1)
Reactor设计模式
优化器
对其填充(Padding)
配置文件的统一管理——通过一个统一的容器去管理(PropertySources)
源代码
Dubbo SPI
当前线程
原持有偏向锁线程释放锁空 | 是否偏向锁(1) | 锁标识(01)
相互请求对方的资源
BService是否注入成功
线程三大特性
Thread.start()
L1 i-Cache
A:Avaliablity(可用性):每个请求都能接受到一个响应,无论响应成功或失败
mysql执行过程
对Spring IOC容器的扩展支持,以及IOC子容器
是
命名区别:第三方以第三方开头XXX-spring-boot-starter官方维护的插件以spring-boot-starter-xxx加载的区别:自身维护的starter组件是通过条件判断是否注入的 第三方维护的不存在条件判断
class文件
將實例放到一級緩存,刪除二三級緩存中A對象
mybatis
ThreadD
Object.notifyObject.notifyAllLockSupport.unpark(Thread)
定义基础的Spring的Context上下文即IOC容器
总线锁与缓存锁
普通对象
解析
Spring表达式语言
升级轻量级锁
ClassPointer指针
WATING
springBoot自动装配机制:就是不再需要你手动注入IoC容器了,各种技术组件帮你完成了Bean对象注入的流程
否
轻量级锁
初始化B對象
线程持有的锁(monitor)
C:consistency(强一致性):所有的节点上的数据时刻保持同步
区别
语句解析
实例数据(Instance Data)
无锁
CPU
thread:nullwaitStatus:0
数组相关
可重入锁
没有
MarkWord 固定8位
spring-instrument
线程调度
高可用、数据一致是很多系统设计的目标,但是分区又是不可避免的
线程访问同步代码块
getBean
无时间等待Thread.sleep()Object.wait()Thread.join()LockSupport.park()
访问同步代码块
調用init初始化方法
底层使用Thread创建线程
開始
唯一途径是通过中断、异常、陷入机制(访管指令) 系统调用(这样做会带来很大的性能开销)
1.通用的curd2.条件构造3.代码生成4.翻页5.批量操作
加锁status++
执行同步体
1
动态Class Loading模块
CAS替换MarkWord
META-INF/services/ 目录 核心类是 ServiceLoader
运行 RUNNING
刪除B標記
在单线程程序中,不会发生“指令重排”和“工作内存和主内存同步延迟”现象,只在多线程程序中出现。编译器重排序,JMM 提供了禁止特定类型的编译器重排序。处理器重排序,JMM 会要求编译器生成指令时,会插入内存屏障来禁止处理器重排序。
Tail
spring-aop
BA:– 响应时间上的损失:正常情况下的搜索引擎 0.5 秒即返回给用户结果,而基本可用的搜索引擎可以在 2 秒作用返回结果。– 功能上的损失:在一个电商网站上,正常情况下,用户可以顺利完成每一笔订单。但是到了大促期间,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面。
GC回收
线程创建
数据一致性
\u0001
Callable<T>
spring-webmvc
互斥锁与悲观锁、独占锁同义,表示某个资源只能被一个线程访问,其他线程不能访问。读-读互斥读-写互斥写-读互斥写-写互斥Java中的同步锁: synchronized
thread:BwaitStatus:-1
OS
ROLL
T1(线程id)/Epoch/1/01
23bit
Epoch
spring-web
可重入锁是一种技术: 任意线程在获取到锁之后能够再次获取该锁而不会被锁所阻塞。可重入锁的原理: 通过组合自定义同步器来实现锁的获取与释放。再次获取锁:识别获取锁的线程是否为当前占据锁的线程,如果是,则再次成功获取。获取锁后,进行计数自增,释放锁:释放锁时,进行计数自减。Java中的可重入锁: ReentrantLock、synchronized修饰的方法或代码段。可重入锁的作用: 避免死锁。面试题1: 可重入锁如果加了两把,但是只释放了一把会出现什么问题?答:程序卡死,线程不能出来,也就是说我们申请了几把锁,就需要释放几把锁。面试题2: 如果只加了一把锁,释放两次会出现什么问题?答:会报错,java.lang.IllegalMonitorStateException。
系统gc
当old区空间足够而且old区可用空间大于新时代的活跃数据内存
spring版本命名规范
主内存
實例化B對象
synchronized、vector、hashtable、ReentrantReadWriteLock中写锁
synchronized、reentrantlock(false)
L1 d-Cache
有序性
synchronized、Reentrantlock、Lock
没有 volatile 修饰的共享表量,线程在操作它的时候会先拷贝到缓存中,然后在缓存中修改,然后在同步到内存中。有 volatile 修饰的共享变量,线程在操作它时,直接在内存中进行操作了,不会再拿到缓存中
MQ(非事务)
分配内存空间
锁标识(00)
将Survivor区中活跃的数据copy到old区
mybatis-plus
依赖注入IOC与DI的最基本实现
Bean对象注入IoC容器的流程* 配置文件的统一管理
ReentrantReadWriteLock中读锁
再尝试
00
spring-core
作用
Seata
IOC
AOP
对象标记
25bit
读写锁
内存系统重排序
TERMINATED终止
1bit
开始偏向锁撤销(等待竞争出现才释放锁的机制)
pring 提供的JDBC抽象框架的主要实现模块,用于简化Spring JDBC操作
ViewResolver
锁粗化
一个新的非堵塞函数式 Reactive Web 框架,可以用来建立异步的,非阻塞,事 件驱动的服务。
ABA
集成AspectJ,AOP应用框架
标记并創建原生的B對象
Resource Manager(RM)– 资源管理器 - 各团队的码农们– 负责对分支事务进行控制,包括分支注册、状态汇报,接收协调器发来的指令,以及对本地事务的开启、提交或回滚。
OS调度
cpu层面
E:Eventually Consistent(最终一致性):上面说软状态,然后不可能一直是软状态,必须有个时间期限。在期限过后,应当保证所有副本保持数据一致性,从而达到数据的最终一致性。这个时间期限取决于网络延时、系统负载、数据复制方案设计等等因素。
一级缓存
實例化對象A
GC分代年龄
spring-test
检测原持有偏向锁的线程状态标识
处于用户态执行时,进程所能访问的内存空间和对象受到限制,其所处于占有的处理器是可被抢占的处于内核态执行时,则能访问所有的内存空间和对象,且所占有的处理器是不允许被抢占的。
轻量级锁状态标识(00)
初始化A對象
无锁状态标识(01)
NettyRemotingServer#start就启动了一个ServerBootstrap并监听9876端口
锁阻塞的情况下Synchronized
共享
暂停原持有偏向锁的线程
双重检查锁
前八位-----1未用 4:年龄 1:偏向锁标记位 2:锁状态位
java中的一个关键字
内存屏障
无锁状态
独占锁是一种思想: 只能有一个线程获取锁,以独占的方式持有锁。和悲观锁、互斥锁同义。Java中用到的独占锁: synchronized,ReentrantLock
撤销偏向锁
公平锁是一种思想: 多个线程按照申请锁的顺序来获取锁。在并发环境中,每个线程会先查看此锁维护的等待队列,如果当前等待队列为空,则占有锁,如果等待队列不为空,则加入到等待队列的末尾,按照FIFO的原则从队列中拿到线程,然后占有锁。
Spring JDBC事务控制实现模块
面向切面编程的应用模块,整合Asm,CGLIb、JDKProxy
springBoot
运行状态 RUNNABLED
3PC
再次判断当前Eden区是否有足够空间
META-INF/dubbo/internal/目录 核心类是 ExtensionLoader
程序计数器Program Counter Register
服务层
ThreadLocalMap
Runnable
指令顺序问题
MVCC
BA:Basically Available(基本可用):假设系统,出现了不可预知的故障,但还是能用,相比较正常的系统而言;
DI
非公平锁
最终执行的指令序列
转变为重量级锁指向重量级锁monitor指针|状态标识(10)
Mark Word(markOop.cpp)
同步锁
CA:如果不要求 P(不允许分区),则 C(强一致性)和 A(可用性)是可以保证的。但其实分区不是你想不想的问题,而是始终会存在,因此 CA 的系统更多的是允许分区后各子系统依然保持 CA。(单体架构)CP:如果不要求 A(可用),相当于每个请求都需要在 Server 之间强一致,而 P(分区)会导致同步时间无限延长,如此 CP 也是可以保证的。很多传统的数据库分布式事务都属于这种模式。AP:要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的 NoSQL 都属于此类。
ReentrantReadWriteLock,CopyOnWriteArrayList、CopyOnWriteArraySet
判断是否有创建代理A对象,有直接返回,没有创建代理A对象
31bit
synchronized、vector、hashtable
原子性
检测当前对象头Mark Word中记录是否是当前线程id
happens-before可见性原则
1.基于POJO的轻量级和最小入侵性编程2.通过依赖注入和面向接口来松耦合3.基于切面和惯性进行声明式编程4.通过切面和模版减少样板式代码
spring-orm
关系:AOP和DI注入都是依赖于IOC容器
Klass Point类型指针
Starter组件
偏向锁状态
互斥锁
thread:DwaitStatus:0
4bit
程序顺序规则
并发基础-top
L3 Cache
轻量级锁是JDK6时加入游戏买号平台地图的一种锁优化机制: 轻量级锁是在无竞争的情况下使用CAS操作去消除同步使用的互斥量。轻量级是相对于使用操作系统互斥量来实现的重量级锁而言的。轻量级锁在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。如果出现两条以上的线程争用同一个锁的情况,那轻量级锁将不会有效,必须膨胀为重量级锁。优点: 如果没有竞争,通过CAS操作成功避免了使用互斥量的开销。缺点: 如果存在竞争,除了互斥量本身的开销外,还额外产生了CAS操作的开销,因此在有竞争的情况下,轻量级锁比传统的重量级锁更慢。
Transaction Coordinator(TC)– 事务协调器 - 技术团队的 leader– 维护全局事务的运行状态,负责协调并驱动全局事务的提交或者回滚
对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。
系统相关
可修饰的结构
Saga
语法解析
锁标识(10)
新对象创建申请空间
synchronized修饰class的代码和this没有太多区别,不一样的点是synchronized修饰的对象不同,当然,通过这个实例,也可以进一步证明synchronized修饰class必须拿到class的锁才能执行synchronized代码块,同一个类下所有实例的线程都会受到影响。synchronized在修饰不同类型数据的时候,锁的粒度(互斥范围)也是不同的(这里只说最大粒度),简单总结就是:方法 > object > class > this。
修饰代码块
Spring帮我们简化了开发
监视器锁规则synchronized
传递性规则
分段锁是一种机制: 最好的例子来说明分段锁是ConcurrentHashMap。ConcurrentHashMap原理:它内部细分了若干个小的 HashMap,称之为段(Segment)。默认情况下一个 ConcurrentHashMap 被进一步细分为 16 个段,既就是锁的并发度。如果需要在 ConcurrentHashMap 添加一项key-value,并不是将整个 HashMap 加锁,而是首先根据 hashcode 得到该key-value应该存放在哪个段中,然后对该段加锁,并完成 put 操作。在多线程环境中,如果多个线程同时进行put操作,只要被加入的key-value不存放在同一个段中,则线程间可以做到真正的并行。线程安全:ConcurrentHashMap 是一个 Segment 数组, Segment 通过继承ReentrantLock 来进行加锁,所以每次需要加锁的操作锁住的是一个 segment,这样只要保证每个 Segment 是线程安全的,也就实现了全局的线程安全
总线
userCache:缓存数据flushCache:清空缓存
分段锁
thread:CwaitStatus:-1
当前线程的栈帧中分配锁记录(Lock Record)
從三級緩存中通過工厰拿到代理A對象
偏向线程ID
偏向锁的获取和释放流程
就绪 READY
连接层(客户端向服务器进行建立连接)
运行时数据区域
指令级并行重排序
自旋锁与自适应自旋(compare and swap)比较并交换。它是指一种操作机制,而不是某个具体的类或方法在许多应用中,锁定状态只会持续很短的时间,为了这么一点时间去挂起恢复线程,不值得。我们可以让等待线程执行一定次数的循环,在循环中去获取锁。这项技术称为自旋锁,它可以节省系统切换线程的消耗,但仍然要占用处理器。在 JDK1.4.2 中,自选的次数可以通过参数来控制。 JDK 1.6又引入了自适应的自旋锁,不再通过次数来限制,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。锁消除虚拟机在运行时,如果发现一段被锁住的代码中不可能存在共享数据,就会将这个锁清除。锁粗化当虚拟机检测到有一串零碎的操作都对同一个对象加锁时,会把锁扩展到整个操作序列外部。如 StringBuffer 的 append 操作。轻量级锁对绝大部分的锁来说,在整个同步周期内都不存在竞争。如果没有竞争,轻量级锁可以使用 CAS 操作避免使用互斥量的开销。偏向锁偏向锁的核心思想是,如果一个线程获得了锁,那么锁就进入偏向模式,当这个线程再次请求锁时,无需再做任何同步操作,即可获取锁。synchronized 是重量级锁,由于消耗太大,虚拟机对其做了一些优化
悲观锁是一种悲观思想,即认为写多读少,遇到并发写的可能性高,每次去拿数据的时候都认为其他线程会修改,所以每次读写数据都会认为其他线程会修改,所以每次读写数据时都会上锁。其他线程想要读写这个数据时,会被这个线程block,直到这个线程释放锁然后其他线程获取到锁.synchronized修饰的方法和方法块、ReentrantLock。
lock()加锁
synchronized
NameServer
刷新主内存数据
Survivor
是否偏移
特权环:R0、R1、R2和R3R0相当于内核态,R3相当于用户态;不同级别能够运行不同的指令集合;
Object.notify()Object.notifyAll()LocakSupport.unpark()
线程2
从安全点继续执行
spring-oxm
指向栈中锁记录的指针
执行代码块
spring-websocket
jdk1.6为了减少锁获取和锁释放的性能消耗引入了偏向锁和轻量级锁来提高锁获取和锁释放的效率
spring-tx
HashCode
start0
否(0)
分布式
ModeAndView
volatile
ThreadC
操作系统的
拷贝对象头中的Mark Word到原持有偏向锁线程的锁记录中
空(CMS过程中用到的标记信息)
返回代理B对象
spring-jms
trhead.run
悲观锁
原生A對象
文本
修饰普通方法
预处理器
对象头中的mark word
恢复线程
concurrentHashMap
Thread真正创建方式
synchronized修饰的代码块叫同步代码块,通常我们需要在synchronized()中指明进入同步代码块的key,这里的key可以是Object、this或者class。在原理上,synchronized修饰代码块是通过monitorenter和monitorexit指令进行同步处理的,在执行monitorenter时必须要拿到key对应的锁才能进入,否则会被阻塞。synchronized(object)表示必须拿到key对象的锁才能执行synchronized代码块,凡是进入该同步代码块中的线程都必须先获得锁this加synchronized不能约束不同实例实例之间的资源共享(线程不安全),相同实例则(线程安全)
自旋
ThreadB
META-INF/spring.factories 文件 核心类是 SpringFactoriesLoader
springBoot-end
ioc容器初始化,將實例化的的對象放到ioc容器中
MESI 协议: 1. M(Modify) 被修改 表示共享数据只缓存在当前 CPU 缓存中,并且是被修改状态,也就是缓存的数据和主内存中的数据不一致。 2. E(Exclusive) 独享的 表示缓存的独占状态,数据只缓存在当前 CPU 缓存中,并且没有被修改 3. S(Shared) 共享的 表示数据可能被多个 CPU 缓存,并且各个缓存中的数据和主内存数据一致4. I(Invalid) 无效的 表示缓存已经失效,不过读或者写都要从主内存和别的缓存读取数据。
View
乐观锁是一种乐观思想,假定当前环境是读多写少,遇到并发写的概率比较低,读数据时认为别的线程不会正在进行修改(所以没有上锁)。写数据时,判断当前与期望值是否相同,如果相同则进行更新(更新期间加锁,保证是原子性的)。Java中的乐观锁: CAS,比较并替换,比较当前值(主内存中的值),与预期值(当前线程中的值,主内存中值的一份拷贝)是否一样,一样则更新,否则继续进行CAS操作。
获取同步锁
统一配置
获取锁
内存区域
初始化
S:Soft State(软状态):相对于原子性而言,要求多个节点的数据副本都是一致的,这是一种“硬状态”。软状态允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点的数据副本存在数据延时。
spring-context
偏向锁是JDK6时加入的一种锁优化机制: 在无竞争的情况下把整个同步都消除掉,连CAS操作都不去做了。偏是指偏心,它的意思是这个锁会偏向于第一个获得它的线程,如果在接下来的执行过程中,该锁一直没有被其他的线程获取,则持有偏向锁的线程将永远不需要再进行同步。持有偏向锁的线程以后每次进入这个锁相关的同步块时,虚拟机都可以不再进行任何同步操作(例如加锁、解锁及对Mark Word的更新操作等)。优点: 把整个同步都消除掉,连CAS操作都不去做了,优于轻量级锁。缺点: 如果程序中大多数的锁都总是被多个不同的线程访问,那偏向锁就是多余的。
返回原生B
1.禁止编译器对代码进行某些优化2.lock 汇编指令,锁住缓存行,启动内存屏障,禁止指令重排,保证有序性与可见性
springMVC九大组件
高速缓存
用户态(User Model)
空/0/01
NameServer每10s扫描brokerLiveTable,检测上次接收到心跳包时间与当前时间相比如果超过120s则broker不可用移除路由表中与broker有关的信息
暂停线程
公平锁
读写锁是一种技术: 通过ReentrantReadWriteLock类来实现。为了提高性能, Java 提供了读写锁,在读的地方使用读锁,在写的地方使用写锁,灵活控制,如果没有写锁的情况下,读是无阻塞的,在一定程度上提高了程序的执行效率。读写锁分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由 jvm 自己控制的。读锁: 允许多个线程获取读锁,同时访问同一个资源。写锁: 只允许一个线程获取写锁,不允许同时访问同一个资源。
可能发生重排序
互斥代码过程
entity{key:threadvalue:THE}
对象在Heap中的布局
spring-jdbc
缓存一致性协议
IO操作
执行同步代码块
写缓存(Store Buffer)跟无效化队列(Invalidate Queue)
实现了Spring MVC(model-view-Controller)的Web应用。
将Java对象映射成XML数据,或者将XML数据映射成Java对象
锁粗化是一种优化技术: 如果一系列的连续操作都对同一个对象反复加锁和解锁,甚至加锁操作都是出现在循环体体之中,就算真的没有线程竞争,频繁地进行互斥同步操作将会导致不必要的性能损耗,所以就采取了一种方案:把加锁的范围扩展(粗化)到整个操作序列的外部,这样加锁解锁的频率就会大大降低,从而减少了性能损耗
屬性注入B對象
原子性:一个操作不能被打断,要么全部执行完毕,要么不执行。在这点上有点类似于事务操作,要么全部执行成功,要么回退到执行该操作之前的状态。
底层实现CAS 主要分三步,读取-比较-修改。其中比较是在检测是否有冲突,如果检测到没有冲突后,其他线程还能修改这个值,那么 CAS 还是无法保证正确性。所以最关键的是要保证比较-修改这两步操作的原子性。CAS 只是保证了操作的原子性,并不保证变量的可见性,因此变量需要加上 volatile 关键字。CAS 本身并未实现失败后的处理机制,它只负责返回成功或失败的布尔值,后续由调用者自行处理。只不过我们最常用的处理方式是重试而已。CAS的ABA 问题CAS 保证了比较和交换的原子性。但是从读取到开始比较这段期间,其他核心仍然是可以修改这个值的。如果核心将 A 修改为 B,CAS 可以判断出来。但是如果核心将 A 修改为 B 再修改回 A。那么 CAS 会认为这个值并没有被改变,从而继续操作。这是和实际情况不符的。解决方案是加一个版本号。AtomicStampedReference:带版本戳的原子引用类型,版本戳为int类型。AtomicMarkableReference:带版本戳的原子引用类型,版本戳为boolean类型。(我们假设一个提款机的例子。假设有一个遵循CAS原理的提款机,小灰有100元存款,要用这个提款机来提款50元。由于提款机硬件出了点问题,小灰的提款操作被同时提交了两次,开启了两个线程,两个线程都是获取当前值100元,要更新成50元。理想情况下,应该一个线程更新成功,一个线程更新失败,小灰的存款值被扣一次。线程1首先执行成功,把余额从100改成50.线程2因为某种原因阻塞。这时,小灰的妈妈刚好给小灰汇款50元线程2仍然是阻塞状态,线程3执行成功,把余额从50改成了100。线程2恢复运行,由于阻塞之前获得了“当前值”100,并且经过compare检测,此时存款实际值也是100,所以会成功把变量值100更新成50。原本线程2应当提交失败,小灰的正确余额应该保持100元,结果由于ABA问题提交成功了。)
判断当前使用S0或S1中是否有足够空间
对象头中的MarkWord的线程id指向当前线程
Bean对象注入IoC容器的流程配置文件的统一管理
死锁
偏向锁标识否(0)
共享锁是一种思想: 可以有多个线程获取读锁,以共享的方式持有锁。和乐观锁、读写锁同义。Java中用到的共享锁: ReentrantReadWriteLock。
执行代码
数组对象
第三方插件
spring模块依赖关系
TCC
LOCK
TIMED_WATING
判断当前Eden区是否有足够空间
ThreadLocalMap默认长度16 下标0开始到15
写屏障(Store Memory Barrier):强制将 Store Buffer 中的内容写入到缓存中或者将该指令之后的写操作写入 store buffer 直到之前的内容被刷入到缓存中,也被称之为 smp_wmb(针对写缓存)读屏障(Load Memory Barrier):强制将 Invalidate Queue 中的内容处理完毕,(针对无效化队列)也被称之为 smp_rmb全屏障(Fence Memory Barrier)
对象hashCode
run
jvm进行Full GC进行回收再次判断是否有足够空间
锁标识(01)
未活动状态/已退出同步代码块
jvm进行Minor GC进行回收不活跃的对象
类元信息
可见性
引用指向分配的内存空间
读取Socket
内核态(Kernel Model)
*****
Head
Regs
32位
unlock()释放锁
优化
加锁和解锁不会带来其他开销
主内存中拷贝对象副本到工作内存中
解析请求
ThreadPoolExecutor
轻量级锁自旋不阻塞
拷贝对象头中的Mark Word到当前线程的锁记录中
乐观锁
CAP理论
(monitor 中记录了锁的持有线程,等待的线程队列)_owner 记录当前持有锁的线程_EntryList 是一个队列,记录所有阻塞等待锁的线程_WaitSet 也是一个队列,记录调用 wait() 方法并还未被通知的线程。
spring-expression
Service Provider Interface),是一种将服务接口与服务实现分离以达到解耦可拔插、大大提升了程序可扩展性的机制。
依赖
编译器优化重排序
指令重排序问题-sb可见性问题-iq
cpu状态
修饰一个代码块,被修饰的代码块被称为同步代码块,其作用的范围是大括号{ }括起来的代码块,作用的对象是调用这个代码块的对象;修饰一个非静态方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
处理器重排序
线程运行结束
原持有偏向锁的线程到到全局安全点
主要为测试提供支持的。
ObjectMonitor争抢锁的实现逻辑
调度算法
并发基础-end
29bit
执行器
二级缓存
运行用户程序
得到原生A对象
GC
原持有偏向锁的线程
存储层
結束
0
AT、TCC、SAGA 和 XA 事务模式
JVM
0 条评论
下一页