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

synchronized 关键字​​ 和 ​​Lock 接口(ReentrantLock)​​ 的详细说明及示例,涵盖核心概念、使用场景、代码实现及两者对比

一、synchronized 关键字

1. 核心特性

  • ​隐式锁​​:自动获取和释放锁(进入同步代码块获取,退出时释放)。
  • ​可重入性​​:同一线程可多次获取同一锁(避免死锁)。
  • ​非公平锁​​:线程获取锁的顺序不保证公平性。
  • ​同步范围​​:通过代码块或方法实现同步。

2. 代码示例

(1) 同步代码块
java
复制
public class Counter {private int count = 0;private final Object lock = new Object();public void increment() {synchronized (lock) { // 锁对象可以是任意对象count++;}}public int getCount() {return count;}
}
(2) 同步方法
java
复制
public class Counter {private int count = 0;// 同步方法(锁对象是当前实例 this)public synchronized void increment() {count++;}// 静态同步方法(锁对象是类的 Class 对象)public static synchronized void staticMethod() {// 静态方法同步逻辑}
}

二、Lock 接口(ReentrantLock)

1. 核心特性

  • ​显式锁​​:需手动调用 lock() 和 unlock()
  • ​可中断​​:支持响应中断(lockInterruptibly())。
  • ​公平锁​​:可配置为公平锁(按请求顺序分配锁)。
  • ​超时机制​​:尝试获取锁时可设置超时时间(tryLock(long, TimeUnit))。
  • ​条件变量​​:通过 newCondition() 创建多个条件队列。

2. 代码示例

(1) 基本用法
java
复制
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Counter {private int count = 0;private final Lock lock = new ReentrantLock();public void increment() {lock.lock();  // 获取锁try {count++;} finally {lock.unlock();  // 必须释放锁(防止死锁)}}public int getCount() {return count;}
}
(2) 公平锁与条件变量
java
复制
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class BoundedBuffer<T> {private final T[] buffer;private int size = 0;private final Lock lock = new ReentrantLock(true); // 公平锁private final Condition notFull = lock.newCondition();private final Condition notEmpty = lock.newCondition();public BoundedBuffer(int capacity) {buffer = (T[]) new Object[capacity];}public void put(T item) throws InterruptedException {lock.lock();try {while (size == buffer.length) {notFull.await(); // 等待缓冲区不满}buffer[size++] = item;notEmpty.signal(); // 通知消费者可取数据} finally {lock.unlock();}}public T take() throws InterruptedException {lock.lock();try {while (size == 0) {notEmpty.await(); // 等待缓冲区不空}T item = buffer[--size];notFull.signal(); // 通知生产者可放数据return item;} finally {lock.unlock();}}
}

三、synchronized 与 Lock 对比

​特性​​synchronized​​Lock(ReentrantLock)​
​锁获取方式​隐式(自动获取/释放)显式(需手动调用 lock() 和 unlock()
​可中断性​不支持支持(lockInterruptibly()
​公平性​仅非公平锁可配置公平/非公平(构造函数参数)
​超时机制​不支持支持(tryLock(long, TimeUnit)
​条件变量​仅一个(通过 wait()/notify()多个(通过 newCondition()
​性能​优化后接近 Lock高并发下更优(减少上下文切换)
​代码简洁性​简单(适合简单同步)灵活(适合复杂场景)

四、使用场景与最佳实践

1. synchronized 适用场景

  • ​简单同步需求​​:如单方法或代码块内的互斥访问。
  • ​代码简洁性优先​​:无需手动管理锁的获取和释放。
  • ​示例​​:单例模式的双重检查锁定。
    java
    复制
    public class Singleton {private static volatile Singleton instance;public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
    }

2. Lock 适用场景

  • ​复杂同步需求​​:如需要公平锁、可中断、超时或条件变量。
  • ​高并发场景​​:需优化锁竞争和性能。
  • ​示例​​:生产者-消费者模型(多条件队列)。
    java
    复制
    public class ProducerConsumer {private final Lock lock = new ReentrantLock();private final Condition notFull = lock.newCondition();private final Condition notEmpty = lock.newCondition();private final Queue<Integer> queue = new LinkedList<>();private static final int CAPACITY = 10;public void produce(int item) throws InterruptedException {lock.lock();try {while (queue.size() == CAPACITY) {notFull.await();}queue.add(item);notEmpty.signal();} finally {lock.unlock();}}public int consume() throws InterruptedException {lock.lock();try {while (queue.isEmpty()) {notEmpty.await();}int item = queue.poll();notFull.signal();return item;} finally {lock.unlock();}}
    }

五、常见问题与解决

1. ​​死锁问题​

  • ​原因​​:多个线程互相持有对方所需锁,导致永久阻塞。
  • ​解决​​:
    • 按固定顺序获取锁(避免循环等待)。
    • 使用 tryLock() 尝试获取锁,超时则释放已持有锁。

2. ​​锁未释放​

  • ​原因​​:Lock 未在 finally 块中释放。
  • ​解决​​:始终在 finally 中调用 unlock()
    java
    复制
    lock.lock();
    try {// 业务逻辑
    } finally {lock.unlock();
    }

六、总结

  • synchronized​:简单易用,适合基础同步场景,但灵活性有限。
  • Lock(ReentrantLock)​​:功能丰富,适合复杂场景(如公平锁、多条件队列),但需手动管理锁。
  • ​选择原则​​:
    • 优先使用 synchronized(代码简洁)。
    • 需要高级功能时选择 Lock(如公平性、超时、多条件)。
http://www.xdnf.cn/news/13032.html

相关文章:

  • 【Elasticsearch】映射:fielddata 详解
  • 【C++特殊工具与技术】优化内存分配(三):operator new函数和opertor delete函数
  • Linux多线程---线程池实现
  • STM32CubeMX-H7-20-ESP8266通信(下)-双单片机各控制一个ESP8266实现通信
  • LLMs 系列科普文(13)
  • 【Java实战】反射操作百倍性能优化
  • MyBatis原理剖析(一)
  • 人工智能学习08-类与对象
  • Python BeautifulSoup解析HTML获取图片URL并下载到本地
  • word中表格线粗细调整
  • 基于单片机的病房呼叫系统(源码+仿真)
  • Linux知识回顾总结----进程状态
  • 什么是ANSYS ACT? ACT又可以分为哪几类?
  • yaklang 中的各种 fuzztag 标签及其用法
  • 跟我学c++中级篇——多线程中的文件处理
  • Java网络编程:构建现代分布式应用的核心技术
  • day50 随机函数与广播机制
  • 基于Java Web的校园失物招领平台设计与实现
  • Redis——主从哨兵配置
  • ckeditor5的研究 (9):写一个自定义插件,包括自定义的toolbar图标、插入当前时间,并复用 CKEditor5 内置的 UI 组件
  • 2025年U盘数据恢复软件推荐:找回丢失文件的得力助手
  • 大数据赋能行业智能化升级:从数据价值到战略落地的全景透视
  • 网络渗透测试中的信息收集与网站目录扫描实战详解
  • Linux --进程控制
  • DHCP / DHCPv6 原理 / 报文解析 / 配置示例
  • Maven入门(够用)
  • Secs/Gem第九讲(基于secs4net项目的ChatGpt介绍)
  • 《光子技术成像技术》第四章 预习2025.6.8
  • 1. Web网络基础 - IP地址核心知识解析
  • 信号与传输介质