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

synchronized关键字的作用、使用场景及锁升级过程。ReentrantLock与synchronized的区别及适用场景。

synchronized关键字的作用、使用场景及锁升级过程。

synchronized关键字的作用

synchronized是Java中的一个关键字,主要用于实现线程之间的同步。它的主要作用包括:

  1. 确保线程互斥地访问同步代码:当一个线程进入synchronized代码块或方法时,它将锁定该对象,其他线程需要等待锁释放后才能进入。这样可以确保在同一时间只有一个线程执行synchronized代码块或方法,从而避免多个线程同时修改共享资源导致的数据不一致或冲突的问题。

  2. 保证共享变量的可见性:synchronized除了实现互斥访问外,还可以保证共享变量的可见性。当一个线程释放锁时,会将对共享变量的更新刷新到主内存中,而当另一个线程获取锁时,会从主内存中重新读取最新的值,保证了线程间的数据可见性。

  3. 保证有序性:synchronized还可以确保代码的执行顺序。一个线程在执行完synchronized代码块或方法后,会释放锁并将对共享变量的修改刷新到主内存,而其他线程获取锁后会从主内存中重新读取最新的值。这样可以保证代码在不同线程间的执行顺序是按照预期的。

使用场景

synchronized常用于以下几种场景:

  1. 多线程需要访问同一资源:如文件、数据库连接或共享数据时,使用synchronized可以防止数据不一致或竞态条件的发生。

  2. 实现生产者-消费者问题、读写操作和初始化需求:在这些场景中,多个线程可能需要按照特定的顺序或规则来访问或修改数据,synchronized可以确保这些操作的正确执行。

  3. 需要对执行的操作进行排队,保证它们按顺序(串行)执行:在某些情况下,为了保证操作的顺序性,需要使用synchronized来同步线程的执行。

锁升级过程

在Java中,synchronized关键字的锁升级是指锁的状态从无锁状态到偏向锁状态,再到轻量级锁状态,最后到重量级锁状态的过程。这个过程是为了提高程序的性能和并发能力:

  1. 无锁状态:当一个线程访问一个同步代码块时,如果没有竞争,那么该线程可以直接进入临界区执行,不需要进行任何锁的操作。

  2. 偏向锁状态:当一个线程访问一个同步代码块时,如果没有竞争,那么该线程会将对象头中的标记位设置为偏向锁,并将线程ID记录在对象头中。下次该线程再次访问同步代码块时,无需进行任何锁的操作,可以直接进入临界区执行。

  3. 轻量级锁状态:当多个线程竞争同一个锁时,偏向锁会升级为轻量级锁。此时,每个线程会在自己的栈帧中创建一个锁记录(Lock Record)来保存锁对象的Mark Word,并尝试使用CAS(Compare and Swap)操作来获取锁。如果CAS操作成功,线程可以进入临界区执行;如果CAS操作失败,表示有其他线程竞争锁,那么线程会膨胀为重量级锁状态。

  4. 重量级锁状态:当多个线程竞争同一个锁时,轻量级锁会升级为重量级锁。此时,竞争锁的线程会进入阻塞状态,操作系统会将其挂起,直到锁被释放。其他线程再次竞争锁时,也会进入阻塞状态。

锁的升级过程是为了在无竞争的情况下尽量减少锁的操作和线程的切换,以提高程序的执行效率。只有在真正发生竞争时,才会升级为重量级锁,以保证线程的正确同步和互斥。

ReentrantLock与synchronized的区别及适用场景。

ReentrantLock与synchronized在Java并发编程中都是用于实现线程同步的重要机制,但它们之间存在一些关键的区别以及不同的适用场景。

一、区别

  1. 锁的获取与释放
    • synchronized:是Java的一个关键字,它隐式地获取和释放锁。当一个线程进入synchronized代码块或方法时,它会自动获取锁;当退出代码块或方法时,锁会自动释放。
    • ReentrantLock:是一个类,实现了Lock接口。它要求显式地调用lock()方法来获取锁,以及显式地调用unlock()方法来释放锁。
  2. 锁的公平性
    • synchronized:总是非公平锁,即无法保证等待时间最长的线程会首先获得锁。
    • ReentrantLock:可以设置为公平锁或非公平锁。在构造ReentrantLock时可以传入一个布尔值,true表示公平锁,false表示非公平锁(默认)。公平锁可以保证按照线程等待的先后顺序来获取锁。
  3. 响应中断
    • synchronized:不响应中断,即一个线程在等待锁的过程中,不能被中断。
    • ReentrantLock:提供了能够响应中断的锁获取操作,如lockInterruptibly()方法,允许在等待锁的过程中响应中断。
  4. 尝试非阻塞地获取锁
    • synchronized:没有提供尝试非阻塞地获取锁的机制。
    • ReentrantLock:提供了tryLock()方法,该方法尝试获取锁,如果获取成功立即返回true,否则返回false,不会使线程阻塞。
  5. 锁绑定多个条件
    • synchronized:与Object类中的wait()、notify()和notifyAll()方法结合,可以实现等待/通知机制,但这种方式较为原始且不够灵活。
    • ReentrantLock:提供了更加丰富的Condition API,每个ReentrantLock对象可以与一个或多个Condition对象(条件变量)关联,这为线程间的协调提供了更为灵活的控制。
  6. 性能
    • 在JDK 6及以后的版本中,synchronized的性能得到了显著提升,引入了偏向锁和轻量级锁等优化技术,使得synchronized在大多数场景下的性能与ReentrantLock相当甚至更优。
    • ReentrantLock在高度竞争的环境下,由于其提供了更灵活的尝试锁定和定时锁定等功能,可能会表现出更好的性能。

二、适用场景

  1. synchronized
    • 适用于简单的同步需求,如只需要基本的互斥访问控制。
    • 对性能要求较高,且不需要复杂同步特性的场景。
    • 开发者希望代码更加简洁,不需要手动管理锁的获取和释放。
  2. ReentrantLock
    • 适用于需要更复杂同步特性的场景,如需要公平锁、可中断锁、尝试非阻塞地获取锁等。
    • 在高度竞争和线程竞争激烈的场景下,ReentrantLock的性能可能优于synchronized。
    • 需要更灵活地控制线程等待和唤醒的场景,如使用多个Condition条件变量进行分组唤醒。

结论

ReentrantLock与synchronized各有优劣,选择哪种同步机制取决于具体的应用场景和需求。在简单的同步需求中,synchronized以其简洁性和良好的性能表现通常是首选;而在需要更复杂同步特性的场景中,ReentrantLock则提供了更灵活和强大的功能。

相关文章:

  • vue使用indexedDB缓存教程
  • BCJR算法——卷积码的最大后验译码
  • Visual Studio代码编辑快捷键
  • 【Golang】关于Go语言数学计算、随机数生成模块--math
  • 损失函数篇 | YOLOv10 更换损失函数之 MPDIoU | 《2023 一种用于高效准确的边界框回归的损失函数》
  • 【数据结构】MapSet
  • Glide基本用法及With方法源码解析
  • Python保留数据删除Excel单元格的函数和公式
  • 通过PHP获取商品详情
  • 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-30
  • 解锁高效开发的秘密武器
  • 无人机之编队控制篇
  • 【无人机设计与控制】Multi-UAV|多无人机多场景路径规划算法MATLAB
  • Spring Cloud全解析:服务调用之OpenFeign集成OkHttp
  • 【C++算法】8.双指针_三数之和
  • CentOS7 安装JDK
  • CentOS7简单部署NFS
  • centos安装java运行环境jdk+tomcat
  • Debian下无root权限使用Python访问Oracle
  • Iterator 和 for...of 循环
  • Less 日常用法
  • PAT A1017 优先队列
  • VUE es6技巧写法(持续更新中~~~)
  • Vue.js-Day01
  • win10下安装mysql5.7
  • 半理解系列--Promise的进化史
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 前端攻城师
  • 在electron中实现跨域请求,无需更改服务器端设置
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • # C++之functional库用法整理
  • #HarmonyOS:Web组件的使用
  • #if 1...#endif
  • #前后端分离# 头条发布系统
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (含答案)C++笔试题你可以答对多少?
  • (三)Kafka 监控之 Streams 监控(Streams Monitoring)和其他
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • (转)scrum常见工具列表
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET C# 操作Neo4j图数据库
  • .NET 设计模式初探
  • .NET 药厂业务系统 CPU爆高分析
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?
  • .pings勒索病毒的威胁:如何应对.pings勒索病毒的突袭?
  • @Async注解的坑,小心
  • @RequestBody与@ResponseBody的使用
  • @SuppressWarnings(unchecked)代码的作用
  • [ C++ ] STL---stack与queue
  • [20160902]rm -rf的惨案.txt
  • [ACM独立出版]2024年虚拟现实、图像和信号处理国际学术会议(ICVISP 2024)
  • [Android]Android开发入门之HelloWorld