【jvm】07-偏向锁、轻量锁、重量锁到底是啥?
【jvm】07-偏向锁、轻量锁、重量锁到底是啥?
欢迎关注b站账号/公众号【六边形战士夏宁】,一个要把各项指标拉满的男人。该文章已在github目录收录。
屏幕前的大帅比和大漂亮如果有帮助到你的话请顺手点个赞、加个收藏这对我真的很重要。别下次一定了,都不关注上哪下次一定。
1.概述
多任务处理在现代计算机操作系统中几乎已是一项必备的功能了。在许多场景下,让计算机同时 去做几件事情,不仅是因为计算机的运算能力强大了,还有一个很重要的原因是计算机的运算速度与 它的存储和通信子系统的速度差距太大,大量的时间都花费在磁盘I/O、网络通信或者数据库访问上。这个在 一行代码完成多线程有写过如何分配线程,原理基本一致。
由于计算机 的存储设备与处理器的运算速度有着几个数量级的差距,所以现代计算机系统都不得不加入一层或多 层读写速度尽可能接近处理器运算速度的高速缓存(Cache) 来作为内存与处理器之间的缓冲,但同时引入新的问题即缓存一致性Java虚拟机的即时编译器中也有指令重排序 (Instruction Reorder)优化(详见)。
2.java内存模型
2.1.主内存与工作内存
主内存直接对应于物理硬件的内存,而为了获取更好的运行速度,虚拟机(或者是硬件、操作系统本身的优化措施)可能会让工作内存优先存储于寄存器和高速缓存中,因为程序运行时主要访问的是工作内存。
2.2.内存间交互操作
Java内存模型中定义了以下8种操作来完成:lock(锁定)\unlock(解锁)\read(从主内存读取到工作内存中)\load(放入工作内存副本)\use(载入执行引擎)\assign(赋值)\store(传递至主内存)\write(写入主内存)。即不允许read和load、store和write操作之一单独出现。对一个变量执行unlock操作之前,必须先把此变量同步回主内存中(执行store、write操作)等
2.3.volatile
可以被认为是轻量级同步,仅保证可见性,如下代码则会发现线程2永远不会打印hello,但是当加入volatile就可以打印了
/**
* @author seal email:876651109@qq.com
* @date 2020/11/22 3:20 PM
* @description
*/
public class Concurrence {
public boolean v = false;
// public volatile boolean v = false;
public static void main(String[] args) {
Concurrence c = new Concurrence();
Thread thread1 = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
c.v = true;
System.out.println(c.v);
});
Thread thread2 = new Thread(() -> {
while (true){
if (c.v) {
System.out.println("hello");
}
}
});
thread2.start();
thread1.start();
while (true) {
}
}
}
2.4.long和double型变量的特殊规则
因为过去对于这两个值特别的存储方式使其并非原子性,但在JDK9以后可以使用-XX:+AlwaysAtomicAccesses开启
2.5.原子性、可见性与有序性
原子性:java内存模型中的除lock和unlock外其他6个均具备原子性,synchronized为大范围原子性操作。
可见性:除了volatile之外,Java还有两个关键字能实现可见性,它们是synchronized和final.
有序性:volatile和synchronized
3.java与线程
3.1.内核线程
程序一般不会直接使用内核线程,而是使用内核线程的一种高级接口——轻量级进程(Light Weight Process,LWP),轻量级进程就是我们通常意义上所讲的线程
3.2.线程调度
调度主要方式有两种,分别是协同式(Cooperative Threads-Scheduling)线程调度和抢占式(Preemptive Threads-Scheduling)线程调度。但前者并不稳定。
3.3.状态转换
6种线程状态:新建(new)\运行(start)\无限期等待(需被显式唤醒,主要有wait、join未设置参数)\限期等待(sleep、wait、join等)、阻塞(synchronized)、结束(shutdown)
4.java与协程
4.1.用户线程
用户线程需要自行维护不如内核线程方便使用,但这部分可以交由虚拟机完成,目前仍在fork/join中研发。研发成熟可以让线程切换消耗更低的资源,而且更加轻量仅占1MB
5.线程安全
5.1.Java语言中的线程安全
5.1.1.不可变
String、final以及基本数据类型
5.1.2.绝对线程安全
synchronized修饰
5.1.3.相对线程安全
例如vector、HashTable等使用同步手段
5.2.线程安全的实现方法
5.2.1.互斥同步
synchronized以及JDK5后新起的java.util.concurrent.locks.Lock
5.2.2.非阻塞同步
即CAS等实现
6.锁优化(AQS)
6.1.自旋锁与自适应自旋
即有限次数的while(true),优点是避免线程切换
6.2.锁消除
例如某个同步方法中全程使用线程安全方法
6.3.锁粗化
例如在循环中不停加锁解锁,则直接会移到循环外面
6.4.轻量级锁
如果整个过程jvm判断只有无竞争但有多个线程可能会使用时进行替换,由CAS实现,如果竞争过多则变为重量锁
6.5.偏向锁
如果整个过程jvm判断没有竞争关系,则进行锁消除处理,在该锁被其它线程获取时依据轻量锁标记判断退化为轻量锁还是重量锁
参考资料
《深入理解Java虚拟机》-周志明
【jvm】07-偏向锁、轻量锁、重量锁到底是啥?的更多相关文章
- java 偏向锁,轻量锁,重量级锁
synchronized的执行过程: 1. 检测Mark Word里面是不是当前线程的ID,如果是,表示当前线程处于偏向锁 2. 如果不是,则使用CAS将当前线程的ID替换Mard Word,如果成功 ...
- 重量级锁synchronized的优化----自旋锁、自适应自旋锁、锁消除、锁粗化
synchronized是重量级锁,效率不高.但在jdk 1.6中对synchronize的实现进行了各种优化,使得它显得不是那么重了.jdk1.6对锁的实现引入了大量的优化,如自旋锁.自适应自旋锁. ...
- synchronized实现原理及其优化-(自旋锁,偏向锁,轻量锁,重量锁)
1.synchronized概述: synchronized修饰的方法或代码块相当于并发中的临界区,即在同一时刻jvm只允许一个线程进入执行.synchronized是通过锁机制实现同一时刻只允许一个 ...
- Java synchronized实现原理总结和偏量锁、轻量锁、重量锁、自旋锁
synchronized实现同步的基础:Java中的每一个对象都可以作为锁.具体表现为以下3种形式. 对于普通同步方法,锁是当前实例对象(this). 对于静态同步方法,锁是当前类的Class对象. ...
- 通俗易懂 悲观锁、乐观锁、可重入锁、自旋锁、偏向锁、轻量/重量级锁、读写锁、各种锁及其Java实现!
网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底 ...
- 写文章 通俗易懂 悲观锁、乐观锁、可重入锁、自旋锁、偏向锁、轻量/重量级锁、读写锁、各种锁及其Java实现!
网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底 ...
- synchronized与static synchronized 的差别、synchronized在JVM底层的实现原理及Java多线程锁理解
本Blog分为例如以下部分: 第一部分:synchronized与static synchronized 的差别 第二部分:JVM底层又是怎样实现synchronized的 第三部分:Java多线程锁 ...
- Linux 自旋锁,互斥量(互斥锁),读写锁
自旋锁(Spin Lock) 自旋锁类似于互斥量,不过自旋锁不是通过休眠阻塞进程,而是在取得锁之前一直处于忙等待的阻塞状态.这个忙等的阻塞状态,也叫做自旋. 自旋锁通常作为底层原语实现其他类型的锁. ...
- java里的锁总结(synchronized隐式锁、Lock显式锁、volatile、CAS)
一.介绍 首先, java 的锁分为两类: 第一类是 synchronized 同步关键字,这个关键字属于隐式的锁,是 jvm 层面实现,使用的时候看不见: 第二类是在 jdk5 后增加的 Lock ...
随机推荐
- nodejs-Cluster模块
JavaScript 标准参考教程(alpha) 草稿二:Node.js Cluster模块 GitHub TOP Cluster模块 来自<JavaScript 标准参考教程(alpha)&g ...
- 【Other】逻辑分析仪的使用(UART、SPI)
首先上一张接线示意图 上方是UART的接线方式,下方则是SPI的 事实上,这样接就能收到信号了 如果是SPI,要设定自己为主机,UART则没有这个问题 下面来说明逻辑分析仪的界面设定 设定介绍完了 下 ...
- clickhouse 输入输出格式
TabSeparated.TabSeparatedRaw.TabSeparatedWithNames和TabSeparatedWithNamesAndTypes TabSeparated 默认格式,缩 ...
- this指针的用法和基本分析
当在不同的对象中采用this指针,就已经是在给它赋值了.对象各自的this指针指向各自对象的首地址,所以不同对象的this指针一定指向不同的内存地址. this 指针是由系统自动提供的指向对象的特殊指 ...
- 使用Lock接口来解决线程安全的问题
package cn.itcast.demo16.Demo09.Lock;import java.util.concurrent.locks.Lock;import java.util.concurr ...
- 机器学习算法中的评价指标(准确率、召回率、F值、ROC、AUC等)
参考链接:https://www.cnblogs.com/Zhi-Z/p/8728168.html 具体更详细的可以查阅周志华的西瓜书第二章,写的非常详细~ 一.机器学习性能评估指标 1.准确率(Ac ...
- Nginx模块之stub_status
目录 一.介绍 二.使用 三.参数 一.介绍 Nginx中的stub_status模块主要用于查看Nginx的一些状态信息. 当前默认在nginx的源码文件中,不需要单独下载 二.使用 本模块默认是不 ...
- AD小白如何发板厂制板--导出gerber文件和钻孔文件+嘉立创下单教程
AD如何发工程制板子? 方式1,发PCB源文件给板厂 方式2,发一些工艺文件给板厂,这样就无须泄漏你的PCB源文件了,一个硬件工程师必须要掌握方式2. 方式2要做的就是导出gerber文件和钻孔文件, ...
- postgresql很强大,为何在中国,mysql成为主流?
你找一个能安装起来的数据库,都可以学,不管什么版本. 数据库的基本功,是那些基本概念(SQL,表,存储过程,索引,锁,连接配置等等),这些在任何一个版本中都是一样的. 目录 postgresql很强大 ...
- Python 字典是如何解决哈希冲突的
本文主要翻译自 so 上面的问题 Why can a Python dict have multiple keys with the same hash? 下 Praveen Gollakota 的答 ...