【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. Android权限级别(protectionLevel)

    通常情况下,对于需要付费的操作以及可能涉及到用户隐私的操作,我们都会格外敏感. 出于上述考虑以及更多的安全考虑,Android中对一些访问进行了限制,如网络访问(需付费)以及获取联系人(涉及隐私)等. ...

  2. fastJson序列化

    在pojo实体中有map<String,Object>的属性,有个key是user它存储在数据库中是用户的id数组,而在aop里会对这个属性做用户详细信息查询并重新put给user.在做J ...

  3. 解决ViewPager与ScrollView 冲突

    ViewPager来实现左右滑动切换tab,如果tab的某一项中嵌入了水平可滑动的View就会让你有些不爽,比如想滑动tab项中的可水平滑动的控件,却导致tab切换. 因为Android事件机制是从父 ...

  4. delete() and free() in C++

    In C++, delete operator should only be used either for the pointers pointing to the memory allocated ...

  5. ES在项目中的测试

    1.application.yml server: port: ${port:40100}spring: application: name: xc-search-servicexuecheng: e ...

  6. 常用windows命令和Dos命令

    Windows常用快捷键 Ctrl + C :复制 Ctrl + V :粘贴 Ctrl + X :剪切 Ctrl + A :全选 Ctrl + Z :撤销(做错了后退一步) Ctrl + Y :向前一 ...

  7. 『与善仁』Appium基础 — 21、元素的基本操作

    目录 1.元素的基本操作说明 (1)点击操作 (2)清空操作 (3)输入操作 2.综合练习 1.元素的基本操作说明 (1)点击操作 点击操作:click()方法.(同Selenium中使用方式一致) ...

  8. 【简】题解 AWSL090429 【聚会】

    这题直接换根dp 记录在要转移的点的子树中有多少牛 #include<bits/stdc++.h> using namespace std; #define ll long long #d ...

  9. Springboot 入门及Demo

    一:SpringBoot入门1.1:SpringBoot简介Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的 ...

  10. 关于UML类图方面的问题(连载)

    UML类图符号:类中属性的可见性主要包括公有(public).私有(Private)和受保护(Protected).在UML中,公有类型的用"+"表达,私有类型用"-&q ...