synchronize 或者lock 锁常见的使用场景

news2025/4/15 17:45:01

在 Java 多线程编程中,synchronizedLock(如 ReentrantLock)是两种常见的线程同步机制。以下是它们的核心区别和典型使用场景,结合代码示例说明:


一、synchronized 的常见场景

1. 简单的临界区保护
public class Counter {
    private int count = 0;
    
    // synchronized 修饰方法(锁对象为当前实例)
    public synchronized void increment() {
        count++;
    }
    
    // synchronized 代码块(显式指定锁对象)
    public void decrement() {
        synchronized(this) {
            count--;
        }
    }
}

适用场景

  • 快速实现线程安全的单例模式、计数器等简单同步逻辑
  • 不需要手动释放锁,避免锁泄漏风险
2. 类级别锁
public class Logger {
    // 锁对象为 Class 对象
    public static synchronized void log(String message) {
        System.out.println(Thread.currentThread().getName() + ": " + message);
    }
}

适用场景

  • 需要全局唯一的锁(如静态方法同步)
3. 对象内部状态保护
public class BankAccount {
    private double balance;
    
    public synchronized void transfer(BankAccount target, double amount) {
        if (this.balance >= amount) {
            this.balance -= amount;
            target.balance += amount;
        }
    }
}

适用场景

  • 保护对象内部状态的原子性操作(如账户转账)

二、Lock 的常见场景

1. 非阻塞尝试获取锁
public class Cache {
    private final ReentrantLock lock = new ReentrantLock();
    private Map<String, Object> data = new HashMap<>();

    public boolean tryUpdate(String key, Object value) {
        if (lock.tryLock()) {  // 尝试获取锁,失败立即返回
            try {
                data.put(key, value);
                return true;
            } finally {
                lock.unlock();
            }
        }
        return false;
    }
}

适用场景

  • 高并发下避免线程阻塞(如缓存更新、限流逻辑)
2. 可中断的锁等待
public class TaskQueue {
    private final ReentrantLock lock = new ReentrantLock();
    private Queue<Runnable> queue = new LinkedList<>();

    public Runnable getTask() throws InterruptedException {
        lock.lockInterruptibly();  // 允许被中断的锁等待
        try {
            while (queue.isEmpty()) {
                Condition notEmpty = lock.newCondition();
                notEmpty.await();
            }
            return queue.poll();
        } finally {
            lock.unlock();
        }
    }
}

适用场景

  • 需要响应中断的任务调度(如线程池任务队列)
3. 公平锁
public class TicketSystem {
    // 公平锁(按请求顺序分配锁)
    private final ReentrantLock lock = new ReentrantLock(true); 
    private int tickets = 100;

    public void buyTicket() {
        lock.lock();
        try {
            if (tickets > 0) {
                System.out.println(Thread.currentThread().getName() + " buys ticket " + tickets--);
            }
        } finally {
            lock.unlock();
        }
    }
}

适用场景

  • 需要避免线程饥饿(如票务系统、资源按顺序分配)
4. 读写锁分离
public class ConfigManager {
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock private Map<String, String> config = new HashMap<>();

    // 读操作(共享锁)
    public String getConfig(String key) {
        rwLock.readLock().lock();
        try {
            return config.get(key);
        } finally {
            rwLock.readLock().unlock();
        }
    }

    // 写操作(独占锁)
    public void updateConfig(String key, String value) {
        rwLock.writeLock().lock();
        try {
            config.put(key, value);
        } finally {
            rwLock.writeLock().unlock();
        }
    }
}

适用场景

  • 读多写少的场景(如配置管理、缓存系统)

三、如何选择?

特性synchronizedLock
锁释放自动释放(代码块/方法退出时)必须手动调用 unlock()
可中断性不支持支持 (lockInterruptibly())
超时机制不支持支持 (tryLock(long, TimeUnit))
公平锁非公平锁(默认)可配置公平锁
锁绑定多个条件不支持支持 (newCondition())
性能JDK6 后优化较好(偏向锁/轻量级锁)高竞争场景下性能更优

四、高频面试点

  1. 锁升级过程(偏向锁 → 轻量级锁 → 重量级锁)
  2. synchronized 的底层实现(对象头 Mark Word、Monitor 机制)
  3. AQS(AbstractQueuedSynchronizer)原理(Lock 的底层实现)
  4. 死锁避免方法(如按固定顺序获取锁、使用 tryLock
  5. 锁粒度优化(如缩小同步代码块范围)

五、陷阱提醒

  • ❌ 在循环中调用 tryLock() 时未设置超时,可能导致 CPU 空转
  • ❌ 忘记在 finally 块中释放 Lock,造成锁泄漏
  • ❌ 错误使用 synchronized 修饰静态方法和实例方法,导致锁对象混淆

掌握这些核心场景和底层原理,可以更好地回答面试中的锁相关问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2334580.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt触摸屏隐藏鼠标指针

Qt触摸屏隐藏鼠标指针 Chapter1 Qt触摸屏隐藏鼠标指针 Chapter1 Qt触摸屏隐藏鼠标指针 使用Qt开发的屏幕软件HMI不需要显示鼠标&#xff0c;qt设置&#xff0c;可以在只启动HMI的时候隐藏光标&#xff0c;退出时再显示。 1.如果只希望在某个 widget 中不显示鼠标指针&#xf…

LangGraph——Agent AI的持久化状态

LangGraph 内置了一个持久化层&#xff0c;通过检查点(checkpointer)机制实现。当你使用检查点器编译图时&#xff0c;它会在每个超级步骤(super-step)自动保存图状态的检查点。这些检查点被存储在一个线程(thread)中&#xff0c;可在图执行后随时访问。由于线程允许在执行后访…

【双指针】专题:LeetCode 1089题解——复写零

复写零 一、题目链接二、题目三、算法原理1、先找到最后一个要复写的数——双指针算法1.5、处理一下边界情况2、“从后向前”完成复写操作 四、编写代码五、时间复杂度和空间复杂度 一、题目链接 复写零 二、题目 三、算法原理 解法&#xff1a;双指针算法 先根据“异地”操…

【C++初学】C++核心编程(一):内存管理和引用

前言 在C的世界里&#xff0c;面向对象编程&#xff08;OOP&#xff09;是核心中的核心。它不仅是一种编程范式&#xff0c;更是一种思考问题的方式。本文将带你从C的内存分区模型出发&#xff0c;深入探讨引用、函数、类和对象、继承、多态以及文件操作等核心概念。通过丰富的…

(PC+WAP)大气滚屏网站模板 电气电力设备网站源码下载

源码介绍 (PCWAP)大气滚屏网站模板 电气电力设备网站源码下载。PbootCMS内核开发的网站模板&#xff0c;该模板适用于滚屏网站模板、电气电力设备网站源码等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#xff1b;PCWAP&#xff0c…

笔试专题(九)

文章目录 十字爆破&#xff08;暴力&#xff09;题解代码 比那名居的桃子&#xff08;滑动窗口/前缀和&#xff09;题解代码 分组&#xff08;暴力枚举 优化二分&#xff09;题解代码 十字爆破&#xff08;暴力&#xff09; 题目链接 题解 1. 暴力 预处理 2. 如果单纯的暴…

3 VS Code 配置优化与实用插件推荐:settings.json 详解、CodeGeeX 智能编程助手及插件离线安装方法

1 优化 settings.json 文件 1.1 settings.json 简介 settings.json 是 VS Code 的核心配置文件&#xff0c;用于存储用户的个性化设置和偏好。通过该文件&#xff0c;用户可以自定义和覆盖 VS Code 的默认行为&#xff0c;包括但不限于以下方面&#xff1a; 编辑器外观&#…

TA学习之路——1.6 PC手机图形API介绍

1前言 电脑的工作原理&#xff1a;电脑是由各种不同的硬件组成&#xff0c;由驱动软件驱使硬件进行工作。所有的软件工程师都会直接或者间接的使用到驱动。 定义&#xff1a;是一个图形库&#xff0c;用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序接口&#xff08;API)。…

Matlab 调制信号和fft变换

1、内容简介 Matlab 194-调制信号和fft变换 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略

100M/1000M 以太网静电浪涌防护方案

方案简介 以太网是一种生产较早且广泛应用的局域网通讯方式&#xff0c;同时也是一种协议&#xff0c;其核 心在于实现区域内&#xff08;如办公室、学校等&#xff09;的网络互联。根据数据传输速度的不同&#xff0c;以 太网大致可以划分为几个等级&#xff1a;标准以太网…

C语言中while的相关题目

一、题目引入 以下程序中,while循环的循环次数是多少次? 二、代码分析 首先要明确的一点 while循环是当循环条件为真 就会一直循环 不会停止 while中i是小于10的 说明i可以取到0 1 2 3 4 5 6 7 8 9 进入第一个if判断i小于1为真时执行continue i0是为真的 执行continue 后…

「Unity3D」图片导入选项取消Read/Write,就无法正确显示导入大小,以及Addressable打包无法正确显示的问题

如果在Edit -> Project Settings -> Editor中的“Load texture data on demand”勾选&#xff0c;就会让图片导入设置中&#xff0c;不勾选Read/Write&#xff0c;就无法正确显示纹理的大小数字。 更进一步的问题是&#xff0c;使用Addressable打包的时候&#xff0c; 如…

Xcode为不同环境配置不同的环境变量

一般有三种方式&#xff1a; 一、通过多Target 二、通过scheme,也就是多configurations 三、通过.xcconfig文件 先来看第二种方式&#xff1a;通过scheme,也就是多configurations,包括自定义User-settings 第一步&#xff1a;增加configurations,Xcode默认为我们生成了…

阿里通义实验室发布图片数字人项目LAM,实现高保真重建

简介 LAM项目结合了3D Gaussian Splatting&#xff08;高斯点云渲染&#xff09;和大规模预训练模型的优势&#xff0c;解决了传统头部重建方法效率低、依赖多数据的痛点。其背景源于AI生成内容&#xff08;AIGC&#xff09;领域对实时、高保真3D头像生成的需求&#xff0c;尤其…

镜像端口及观察端口的配置

配好路由器的各个接口的IP PC1ping PC3的IP&#xff0c;在路由器中抓2/0/0端口的包&#xff0c;可观察到无结果 输入observe-port interface g 2/0/0 命令配置观察端口 输入mirror to observe-port both命令 &#xff08;其中both表示接收来去的数据包&#xff0c;inboun…

STM32——I2C通讯(软件模拟)

I2C概念 I2C:Inter-Integrated Circuit&#xff08;内部集成电路&#xff09; Philps公司80年代初期开发的&#xff0c;引脚少&#xff0c;硬件实现简单&#xff0c;可扩展性广泛地使用在系统内多个集成电路&#xff08;IC&#xff09;间的低速通讯 简单的双向两线制总线协议…

JetBrains Terminal 又发布新架构,Android Studio 将再次迎来新终端

不到一年的时间&#xff0c;JetBrains 又要对 Terminal 「大刀阔斧」&#xff0c;本次发布的新终端是重构后的全新的架构&#xff0c;而上一次终端大调整还是去年 8 月的 v2024.2 版本&#xff0c;并且在「Android Studio Ladybug | 2024.2.1」也被引入。 不知道你们用不用内置…

论文:Generalized Category Discovery with Large Language Models in the Loop

论文下载地址&#xff1a;Generalized Category Discovery with Large Language Models in the Loop - ACL Anthology 1、研究背景 尽管现代机器学习系统在许多任务上取得了优异的性能&#xff0c;绝大多数都遵循封闭世界的设置&#xff0c;假设训练和测试数据来自同一组预定义…

第十六届蓝桥杯 省赛C/C++ 大学B组

编程题目现在在洛谷上都可以提交了。 未完待续&#xff0c;写不动了。 C11 编译命令 g A.cpp -o A -Wall -lm -stdc11A. 移动距离 本题总分&#xff1a;5 分 问题描述 小明初始在二维平面的原点&#xff0c;他想前往坐标 ( 233 , 666 ) (233, 666) (233,666)。在移动过程…

【计网】网络交换技术之分组交换(复习自用,重要1)

复习自用的&#xff0c;处理得比较草率&#xff0c;复习的同学或者想看基础的同学可以看看&#xff0c;大佬的话可以不用浪费时间在我的水文上了 另外两种交换技术可以直接点击链接访问相关笔记&#xff1a; 电路交换 报文交换 一、分组交换的定义 1.定义 分组交换&#x…