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

Java 开发中锁的选择与使用

Java 开发中锁的选择与使用

        • 1. 引言
        • 2. Java 中的锁机制
        • 3. synchronized 关键字
          • 示例
          • 好处
          • 注意点
        • 4. ReentrantLock 类
          • 示例
          • 好处
          • 注意点
        • 5. ReadWriteLock 接口
          • 示例
          • 好处
          • 注意点
        • 6. Atomic 类
          • 示例
          • 好处
          • 注意点
        • 7. 锁的选择与对比

1. 引言

在并发编程中,锁是一种常见的机制,用于解决多线程环境下的资源共享问题。合理地使用锁可以有效地提高程序的正确性和性能。

2. Java 中的锁机制

Java 提供了多种锁机制,主要包括:

  • synchronized 关键字
  • ReentrantLock 类
  • ReadWriteLock 接口
  • Atomic 类
3. synchronized 关键字

synchronized 是 Java 语言内置的关键字,可以修饰方法或者同步代码块,使得同一时刻只有一个线程可以执行被同步的代码段。

示例
public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}
好处
  • 简单易用synchronized 的使用非常直观,易于理解和实现。
  • 隐式锁管理:JVM 自动管理锁的获取和释放,减少了手动管理锁的复杂度。
注意点
  • 死锁风险:如果多个 synchronized 块或方法使用不同的对象作为锁,则有可能引发死锁。
  • 不可中断:如果一个线程已经获得了锁,其他线程只能等待,除非持有锁的线程抛出异常或主动释放锁。
  • 性能问题:在高并发环境下,synchronized 可能会导致性能瓶颈。
4. ReentrantLock 类

ReentrantLock 是 Java 并发库中的一个类,提供了比 synchronized 更多的功能,如可中断、公平锁、尝试锁等。

示例
import java.util.concurrent.locks.ReentrantLock;

public class Counter {
    private int count = 0;
    private final ReentrantLock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public int getCount() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
}
好处
  • 可中断性:等待锁的线程可以被中断。
  • 公平锁:可以选择是否使用公平锁策略,公平锁可以按照请求锁的顺序进行分配。
  • 尝试锁:可以尝试获取锁而不立即阻塞。
注意点
  • 手动管理锁:需要显式地获取和释放锁,否则可能导致资源泄露。
  • 性能开销:相比 synchronizedReentrantLock 可能会有一定的性能开销。
5. ReadWriteLock 接口

ReadWriteLock 是一种特殊的锁机制,允许多个线程同时读取共享资源,但在写入时独占资源。这在读操作远多于写操作的场景下非常有用。

示例
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReadWriteLock;

public class DataStore {
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private String data = "";

    public void writeData(String newData) {
        lock.writeLock().lock();
        try {
            data = newData;
        } finally {
            lock.writeLock().unlock();
        }
    }

    public String readData() {
        lock.readLock().lock();
        try {
            return data;
        } finally {
            lock.readLock().unlock();
        }
    }
}
好处
  • 读写分离:允许多个线程同时读取共享资源,提高了并发性能。
  • 减少阻塞:读操作不会阻塞其他读操作,只有写操作才会阻塞其他读写操作。
注意点
  • 复杂性增加:使用 ReadWriteLock 需要更复杂的锁管理逻辑。
  • 公平性问题:默认的 ReentrantReadWriteLock 不是公平锁,可能会影响性能。
6. Atomic 类

Atomic 类提供了一种无锁的原子更新方式,适用于简单的数据类型更新,如 AtomicIntegerAtomicLong 等。

示例
import java.util.concurrent.atomic.AtomicInteger;

public class Counter {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }
}
好处
  • 无锁更新:适用于简单的数据类型更新,可以避免锁的开销。
  • 性能优化:在单线程或多线程环境下都能提供较好的性能。
注意点
  • 适用范围有限:仅适用于简单的数据类型更新,不适用于复杂的业务逻辑。
  • 线程安全性限制:对于复杂的业务逻辑,仍需使用其他锁机制来保证线程安全。
7. 锁的选择与对比

选择锁的方式应根据具体的应用场景和需求来决定:

  • 简单同步:如果只需要简单的同步控制,并且不关心锁的高级特性,可以使用 synchronized
  • 高级功能:如果需要更高级的锁功能,如公平锁、非阻塞锁尝试、中断等待锁的能力等,应该使用 ReentrantLock
  • 读多写少:如果场景中读操作远多于写操作,可以考虑使用 ReadWriteLock
  • 原子更新:对于简单的数据类型更新,可以使用 Atomic 类来提高性能。

http://www.kler.cn/news/303351.html

相关文章:

  • MVC设计模式与delegate,tablview,Appdelegate,SceneDelegate
  • 【逐行注释】自适应观测协方差R的AUKF(自适应无迹卡尔曼滤波,MATLAB语言编写),附下载链接
  • 小程序给对象赋值(双向绑定)方法之一
  • 企业客户|基于springboot的企业客户管理系统设计与实现(附项目源码+论文+数据库)
  • 一次开发,多端部署--实例二
  • RK3568 android11 usb摄像头预览分辨率添加多分辨率---解除1080p限制
  • 实现绑定UDP端口的Server程序
  • 大模型微调 - 基于预训练大语言模型的对话生成任务 训练代码
  • 计算机二级自学笔记(选择题1部分)
  • git的快速合并fast-forward merge详解
  • 机器学习和深度学习存在显著区别
  • LeetCode 热题 100 回顾11
  • 【系统架构设计师】ATAM(Architecture Tradeoff Analysis Method)
  • 【免费刷题】实验室安全第一知识题库分享
  • 简单了解深度学习
  • postcss-pxtorem实现页面自适应
  • python爬虫--实用又便捷的第三方模块--requests实战
  • 架构师知识梳理(七):软件工程-测试
  • 【智路】智路OS Perception Pipeline
  • 文件批量添加水印和密码合并单元格完整版
  • Python基础语法(2)
  • 【运维监控】Prometheus+grafana监控spring boot 3运行情况
  • 实现快速产出的短视频剪辑工具
  • Object.entries()
  • 力扣之1783.大满贯数量
  • zabbix之钉钉告警
  • SpringMVC与SpringBoot的区别
  • Docker续9:使用docker-compose部署nmt项目,在haproxy中代理mysql负载均衡
  • k8s的搭建
  • 【Clickhouse】Clickhouse数据库简介