【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-偏向锁、轻量锁、重量锁到底是啥?的更多相关文章

  1. java 偏向锁,轻量锁,重量级锁

    synchronized的执行过程: 1. 检测Mark Word里面是不是当前线程的ID,如果是,表示当前线程处于偏向锁 2. 如果不是,则使用CAS将当前线程的ID替换Mard Word,如果成功 ...

  2. 重量级锁synchronized的优化----自旋锁、自适应自旋锁、锁消除、锁粗化

    synchronized是重量级锁,效率不高.但在jdk 1.6中对synchronize的实现进行了各种优化,使得它显得不是那么重了.jdk1.6对锁的实现引入了大量的优化,如自旋锁.自适应自旋锁. ...

  3. synchronized实现原理及其优化-(自旋锁,偏向锁,轻量锁,重量锁)

    1.synchronized概述: synchronized修饰的方法或代码块相当于并发中的临界区,即在同一时刻jvm只允许一个线程进入执行.synchronized是通过锁机制实现同一时刻只允许一个 ...

  4. Java synchronized实现原理总结和偏量锁、轻量锁、重量锁、自旋锁

    synchronized实现同步的基础:Java中的每一个对象都可以作为锁.具体表现为以下3种形式. 对于普通同步方法,锁是当前实例对象(this). 对于静态同步方法,锁是当前类的Class对象. ...

  5. 通俗易懂 悲观锁、乐观锁、可重入锁、自旋锁、偏向锁、轻量/重量级锁、读写锁、各种锁及其Java实现!

    网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底 ...

  6. 写文章 通俗易懂 悲观锁、乐观锁、可重入锁、自旋锁、偏向锁、轻量/重量级锁、读写锁、各种锁及其Java实现!

    网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底 ...

  7. synchronized与static synchronized 的差别、synchronized在JVM底层的实现原理及Java多线程锁理解

    本Blog分为例如以下部分: 第一部分:synchronized与static synchronized 的差别 第二部分:JVM底层又是怎样实现synchronized的 第三部分:Java多线程锁 ...

  8. Linux 自旋锁,互斥量(互斥锁),读写锁

    自旋锁(Spin Lock) 自旋锁类似于互斥量,不过自旋锁不是通过休眠阻塞进程,而是在取得锁之前一直处于忙等待的阻塞状态.这个忙等的阻塞状态,也叫做自旋. 自旋锁通常作为底层原语实现其他类型的锁. ...

  9. java里的锁总结(synchronized隐式锁、Lock显式锁、volatile、CAS)

    一.介绍 首先, java 的锁分为两类: 第一类是 synchronized 同步关键字,这个关键字属于隐式的锁,是 jvm 层面实现,使用的时候看不见: 第二类是在 jdk5 后增加的 Lock ...

随机推荐

  1. 大数据学习day36-----flume02--------1.avro source和kafka source 2. 拦截器(Interceptor) 3. channel详解 4 sink 5 slector(选择器)6 sink processor

    1.avro source和kafka source 1.1 avro source avro source是通过监听一个网络端口来收数据,而且接受的数据必须是使用avro序列化框架序列化后的数据.a ...

  2. pyqt5 改写函数

    重新改写了keyPressEvent() class TextEdit(QTextEdit): def __init__(self): QtWidgets.QTextEdit.__init__(sel ...

  3. Android EditText软键盘显示隐藏以及“监听”

    一.写此文章的起因 本人在做类似于微信.易信等这样的聊天软件时,遇到了一个问题.聊天界面最下面一般类似于如图1这样(这里只是显示了最下面部分,可以参考微信等),有输入文字的EditText和表情按钮等 ...

  4. java内存管理的小技巧

    1,尽量使用直接量.     采用String str="hello"; 而不是 String str = new String("hello"): 2,使用S ...

  5. 【Spring Framework】Spring注解设置Bean的初始化、销毁方法的方式

    bean的生命周期:创建---初始化---销毁. Spring中声明的Bean的初始化和销毁方法有3种方式: @Bean的注解的initMethod.DestroyMethod属性 bean实现Ini ...

  6. SQL 基础知识终极指南

    什么是数据库? 数据库是以电子方式从系统中存储和检索的大量数据集合. 存储在数据库中的结构化数据被处理.操纵.控制和更新以执行各种操作. 行业中使用的一些流行数据库是 Oracle.MySQL.Pos ...

  7. 其他(Excel函数集团)

    此处文章均为本妖原创,供下载.学习.探讨! 文章下载源是Office365国内版1Driver,如有链接问题请联系我. 请勿用于商业!谢谢 下载地址:https://officecommunity-m ...

  8. 联盛德 HLK-W806 (十一): 软件SPI和硬件SPI驱动ST7567液晶LCD

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

  9. python3 5月26日 time模块常用时间转换 &datetime()模块学习 random()

    import time  获取当前时间: 指定字符串格式:time.strftime("%Y-%m-%d %H:%M:%S") 当前时间戳:time.time() 当前时间元组格式 ...

  10. nginx配置文件简析

    https://blog.csdn.net/wangbin_0729/article/details/82109693 #运行用户 user www-data; #启动进程,通常设置成和cpu的数量相 ...