【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 ...
随机推荐
- Js数组内对象去重
let person = [ {id: 0, name: "小明"}, {id: 1, name: "小张"}, {id: 2, name: "小李& ...
- 生成接口文档并同步到postman
前言 当我们开发需要测试接口时,会遇到以下几个问题 1.如果接口过多,参数过多,一个个参数复制到postman简直能要了我的狗命,重复劳动过多. 2.如果接口过多,参数过多,编写接口文档给测试人员或者 ...
- Java设计模式—Proxy动态代理模式
代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 图 1. 代 ...
- uniapp实现钉钉扫码登录
由于uniapp暂无钉钉授权登录所以本文将钉钉扫码登录作为网页嵌入uniapp,最终实现钉钉扫码登录app 1. 用H5调起钉钉扫码登录 钉钉在网页端的扫码登录可参考钉钉文档:扫码登录第三方网站 - ...
- shell脚本 微信/钉钉验证登录服务器
一.简介 登录用户需要二次验证码进行验证 可以配合 监控用户登录,发送通知给企业微信/钉钉 来使用 脚本放到/etc/profile.d/ 目录,登录的时候自动触发 二.微信脚本 1.需要修改Crop ...
- UCI数据库_鸢尾花数据集的读取方式
1. 读取数据的第一种方式 [attrib1,attrib2,attrib3,attrb4,class] = textread('iris.data','%f%f%f%f%s','delimiter' ...
- Cyber Apocalypse 2021 pwn write up
Controller 考点是整数溢出和scanf函数的引发的栈溢出漏洞,泄露libc地址将返回地址覆盖成one_gadgets拿到shell. 1 from pwn import * 2 3 p = ...
- zabbix保姆级安装教程
安装步骤 1.进入官网选择下载的版本和服务器类型 官网地址:https://www.zabbix.com/cn/download?zabbix=5.0&os_distribution=cent ...
- java 多线程: Thread 锁ReentrantLock 常用方法
注意 reentrantLock 和 同步代码块儿一样,同一个时刻只能一个线程获取锁,也就是共用锁的代码块部分,线程是顺序执行的 ReentrantLock 常用方法 getHoldCount获取当前 ...
- SQL:查询Mysql表结构
背景:有时需要做数据字典,其中最重要的就是表结构.经整理,编写SQL如下: 代码: 1 -- drop TABLE `cfg_data_dict` ; 2 CREATE TABLE `cfg_data ...