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

✨Java并发编程:Synchronized与ReentrantLock的比较

✨探索Java并发编程:Synchronized与ReentrantLock的比较✨

在Java多线程编程中,确保线程安全是至关重要的。为此,Java提供了多种机制来实现同步操作。其中,synchronized关键字和java.util.concurrent.locks.ReentrantLock类是最常用的两种方式。本文将探讨这两种机制之间的主要区别,以帮助开发者更好地选择适合其应用场景的技术。

Synchronized 关键字

synchronized关键字是Java语言内置的一种互斥锁机制,它能够保证在同一时刻只有一个线程可以执行特定的代码段(临界区)。它可以应用于方法级别或代码块级别。

特点:

  • 简洁性:使用简单,直接修饰方法或声明同步代码块。
  • 不可中断:一旦一个线程获取了锁,其他等待该锁的线程必须等到锁被释放,无法强制中断。
  • 自动释放:当发生异常时,JVM会自动释放锁。
  • 非公平锁:默认情况下,synchronized采用的是非公平策略,即先抢到锁的线程可以优先执行。
  • 性能:随着JDK版本更新,如自适应自旋、锁消除等优化技术的应用,synchronized的性能得到了显著提升。

使用Synchronized关键字实现同步

public class SynchronizedExample {// 定义私有变量 count 表示计数private int count = 0;// 使用 synchronized 关键字修饰的方法,实现对 count 的递增操作public synchronized void increment() {count++;}// 使用 synchronized 关键字修饰的方法,获取当前 count 的值public synchronized int getCount() {return count;}public static void main(String[] args) {SynchronizedExample example = new SynchronizedExample();Runnable runnable = () -> {for (int i = 0; i < 1000; i++) {// 每个线程执行 1000 次递增操作example.increment();}};Thread thread1 = new Thread(runnable);Thread thread2 = new Thread(runnable);thread1.start();thread2.start();try {// 等待 thread1 执行完毕thread1.join();// 等待 thread2 执行完毕thread2.join();} catch (InterruptedException e) {e.printStackTrace();}// 输出最终的计数结果System.out.println("Synchronized count: " + example.getCount());}
}

ReentrantLock 类

ReentrantLock是Java 5之后引入的一个显式锁接口Lock的具体实现,它提供了比 synchronized 更加丰富的功能。

特点:

  • 灵活性:支持尝试获取锁、定时等待等功能。
  • 可中断:允许线程在等待锁的过程中响应中断请求。
  • 手动管理:需要程序员手动获取和释放锁,这增加了出错的可能性。
  • 公平/非公平选择:可以通过构造函数参数设置为公平锁或非公平锁。
  • 条件变量:提供Condition对象,可用于更复杂的线程间通信场景。

使用ReentrantLock实现同步

import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockExample {// 定义私有变量 count 表示计数private int count = 0;// 创建 ReentrantLock 对象用于实现同步private ReentrantLock lock = new ReentrantLock();// 实现对 count 的递增操作,使用 ReentrantLock 进行同步public void increment() {lock.lock();try {count++;} finally {// 确保在任何情况下都能释放锁lock.unlock();}}// 获取当前 count 的值public int getCount() {return count;}public static void main(String[] args) {ReentrantLockExample example = new ReentrantLockExample();Runnable runnable = () -> {for (int i = 0; i < 1000; i++) {// 每个线程执行 1000 次递增操作example.increment();}};Thread thread1 = new Thread(runnable);Thread thread2 = new Thread(runnable);thread1.start();thread2.start();try {// 等待 thread1 执行完毕thread1.join();// 等待 thread2 执行完毕thread2.join();} catch (InterruptedException e) {e.printStackTrace();}// 输出最终的计数结果System.out.println("ReentrantLock count: " + example.getCount());}
}

比较总结

特性SynchronizedReentrantLock
使用方便
锁的细粒度控制有限
可中断
公平锁选项
性能现代JVM下接近甚至优于ReentrantLock取决于具体用例

结论

虽然ReentrantLock提供了更多高级特性,但在大多数基本场景下,synchronized已经足够强大且易于使用。只有当你确实需要利用ReentrantLock提供的额外功能时(例如条件变量、可中断锁等),才应考虑使用它。

觉得有用的话可以点点赞 (*/ω\*),支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。


http://www.mrgr.cn/news/41181.html

相关文章:

  • 区块链技术的应用场景和优势
  • 4M-21: An Any-to-Any Vision Model for Tens of Tasks and Modalities论文精度
  • 数字经济与新质生产力:地理信息与遥感视角下的深度分析
  • 在职场,没人告诉你的人情世故
  • dcatadmin 自定义登录页面
  • C++基础补充(01)C++11基于范围的for循环
  • 招联金融秋招内推2025
  • 相机基础概念
  • 【优选算法】(第十六篇)
  • ROM、RAM 和 Flash 的区别
  • <<迷雾>> 第5章 从逻辑学到逻辑电路(6)--莎士比亚电路 示例电路
  • Netty系列-7 Netty编解码器
  • java 日常开发踩坑之LomBok @Data映射为null
  • 高阶数据结构-------图
  • 二.物理层
  • 【Python】2. 变量和数据类型
  • [Linux]从零开始的网站搭建教程
  • 【PostgreSQL】提高篇——PostgreSQL 对 JSON 和数组的支持及其在数据建模中的应用
  • 【C++】单例模式
  • NP-hard问题