当前位置: 首页 > news >正文

【Java】JUC并发(synchronized进阶、ReentrantLock可重入锁)

Synchronized进阶

1、锁升级

        Java 6之后对 synchronized 进行了改进,引入了锁升级机制,锁会根据线程的竞争情况进行升级。方向为 : 无锁 --> 偏向锁 --> 轻量级锁 --> 重量级锁,可以一定程度减少系统的开销。

无锁:一个线程没有被执行时,就会处于无锁状态。

偏向锁:当只有一个线程执行时,会从无锁升级为偏向锁。

轻量级锁:当有多个线程交替执行同步块时,会从偏向锁升级为轻量级锁。

重量级锁:当多个线程并发时,会从轻量级锁升级为重量级锁。

2、锁升级过程

2.1、无锁 ==> 偏向锁

        当只有一个线程执行时,会从无锁升级为偏向锁。会在对象头中的 Mark Word 中存入该线程的ID。此时,锁的状态为偏向锁。

2.2、偏向锁 ==> 轻量级锁

        当有多个线程交替执行同步块时,会从偏向锁升级为轻量级锁。这时在线程的栈中创建锁记录(Lock Record),并通过CAS(Compare and Swap)操作将对象头中的 Mark Word 复制到锁记录中,并将 Mark Word 执行锁记录地址。

2.3、轻量级锁 ==> 重量级锁

        当多个线程并发时,会从轻量级锁升级为重量级锁。也就是当多个线程开始竞争锁时,就要从轻量级锁升级为重量级锁。

3、锁降级

        锁降级,通常是从高级别转变到低级别的过程。一般会发生在:GC垃圾回收的过程中,JVM 会将索状态重置为无锁状态。

4、Synchronized实现原理

        synchronized实现原理主要基于对象头 Monitor (监视器)机制

4.1、对象头

        通常将锁的状态保存在对象头中,对象头主要包含两个部分:Mark WordKlass Pointer

4.1.1、Mark Word
  • 长度:32位 JVM 中占32位(4字节),64位 JVM 中占64位(8字节)
  • 作用:主要存储对象的 哈希值、GC分代年龄、锁状态 等运行时的数据。
  • 特点:Mark Word 的位布局会根据对象的锁状态动态改变。
4.1.2、Klass Pointer
  • 长度:32位 JVM 中占32位(4字节),64位 JVM 中默认开启指针压缩占32位(4字节),不开启是占64位(8字节)。
  • 作用:指向对象所属类的元数据,JVM 通过指针确定对象是那个类的实例。
  • 特点:堆内存超过32GB时自动关闭指针压缩,恢复为8字节。

4.2、Monitor (监视器)

        通常存在于线程栈的锁记录中

5、线程安全的单例模式

public class Test02 {public static void main(String[] args) {Singleton s1 = Singleton.getInstance();Singleton s2 = Singleton.getInstance();Singleton s3 = Singleton.getInstance();System.out.println(s1.hashCode());System.out.println(s2.hashCode());System.out.println(s3.hashCode());}
}
// 线程安全的单利模式
class Singleton{// 构造函数的私有化private Singleton(){}// 静态的内部类private static class Holder{// 单例对象private static final Singleton singleton = new Singleton();}public static Singleton getInstance() {return Holder.singleton;}
}2003749087
2003749087
2003749087

ReentrantLock可重入锁

1、什么事可重入锁

        ReentrantLock是 java.util.concurrent.locks 包下的一个类,它提供了比 Synchronized 更灵活、强大的锁机制。“可重入”意味着同一线程可以多次获取同一把锁,而不会被阻塞。

2、核心方法

2.1、锁操作方法

方法签名描述
void lock()获取锁,如果锁被其他线程持有,则阻塞当前线程
void lockInterruptibly()获取锁,但允许等待时中断
boolean tryLock()尝试以非阻塞的方式获取锁
boolean trayLock(long timeout,TimeUnit unit)在指定时间内尝试获取锁
void unlock()释放锁

2.2、状态查询方法

方法签名描述
boolean isHeldByCurrentThread()查询当前线程是否持有锁
boolean isLocked()查询锁是否被任何线程持有
boolean isFair()判断锁是否为公平锁

2.3、条件变量方法

方法签名描述
Condition newCondition()创建一个与当前锁绑定的条件变量

3、使用案例

3.1、锁的基本使用

public class Test04 {public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();Thread t1 = new Thread(()->{counter.add();});Thread t2 = new Thread(()->{counter.dec();});t1.start();t2.start();t1.join();t2.join();System.out.println(counter.getValue());}
}class Counter{private static int value = 0;// 创建锁对象private final ReentrantLock lock =new ReentrantLock();public static int getValue() {return value;}public void add(){lock.lock();try {for (int i =0 ;i <10000;i++){value++;}} finally {lock.unlock();}}    public  void dec(){lock.lock();try {for (int i =0 ;i <10000;i++){value--;}} finally {lock.unlock();}}
}

3.2、支持中断锁的获取

public class demo1 {public static void main(String[] args) throws InterruptedException {// 创建ReentrantLock锁对象ReentrantLock lock = new ReentrantLock();Thread t1 = new Thread(()->{try {lock.lockInterruptibly();try {System.out.println("线程任务执行!");} finally {lock.unlock();}} catch (InterruptedException e) {System.out.println("线程中断!");return;}System.out.println("子线程结束!");});t1.start();t1.interrupt();System.out.println("主线程结束!");}
}主线程结束!
线程中断!

4、synchronized和synchronized的区别

特性Synchronizedsynchronized
锁的获取与释放隐式调用,由JVM自动完成显示调用,手动调用lock()和unlock()方法
可中断性不可中断可以中断,使用lockInterruptibly()
超时机制不支持支持,使用tryLock(timeout)
公平性非公平非公平和公平都支持
条件变量单一wait/notify支持条件对象Condition
锁状态检测无法判断通过方法可以获取
锁实现机制监听器 Monitor AQS

http://www.dtcms.com/a/283188.html

相关文章:

  • 二重循环:输入行数,打印直角三角形和倒直角三角形
  • Java后端开发核心笔记:分层架构、注解与面向对象精髓
  • 基于Android的旅游计划App
  • Web基础 -MYSQL
  • 冷库耗电高的原因,冷链运营者的降本增效的方法
  • LVS四种模式及部署NAT、DR模式集群
  • CD53.【C++ Dev】模拟实现优先级队列(含仿函数)
  • 【计算机网络】数据通讯第二章 - 应用层
  • 深度学习之反向传播
  • 【迭代】PDF绘本录音播放,点读笔方案调研和初步尝试
  • leetcode 725 分割链表
  • 微算法科技研究量子视觉计算,利用量子力学原理提升传统计算机视觉任务的性能
  • Kafka入门
  • 语音增强论文汇总
  • Go基本数据类型
  • 81、面向服务开发方法
  • Redisson实现分布式锁
  • Redisson实现限流器详解:从原理到实践
  • HTML 入门教程:从零开始学习网页开发基础
  • 前端知识:浏览器工作原理与开发者工具知识笔记
  • WIN10系统优化篇(一)
  • Leetcode 02 java
  • IDEA报错“资源找不到”?重启就好了!!?
  • 使用Dify构建HR智能助理,深度集成大模型应用,赋能HR招聘管理全流程,dify相关工作流全开源。
  • 城市蓝影.
  • 服务注册nacos和OpenFerign(用于封装跨服务之间的调用方法)
  • kubernetes学习笔记(一)
  • 数据结构 双向链表(2)--双向链表的实现
  • 黄仁勋链博会演讲实录:脱掉皮衣,穿上唐装,中文开场
  • 完善评论发布功能