Java 锁机制全面解析

在 Java 并发编程中,锁(Lock)是保证线程安全的关键工具。本文将全面介绍 Java 的锁机制,包括 synchronized 关键字、Lock 接口及其实现、读写锁、乐观锁与悲观锁等,帮助新手理解 Java 并发控制。

1. Java 中的锁概述

锁(Lock)用于控制多个线程对共享资源的访问。不同的锁机制可以提供不同的性能、可重入性、公平性和可中断性等特性。

2. synchronized 关键字

synchronized 是 Java 内置的同步机制,依赖于 Java 虚拟机(JVM)实现。

2.1 用法示例

public class SynchronizedExample {private int count = 0;public synchronized void increment() {count++;}
}

在上述示例中,increment 方法是同步方法,多个线程调用时会自动加锁,保证 count 变量的线程安全。

2.2 synchronized 作用范围

  • 同步实例方法:锁住当前实例(this)。
  • 同步静态方法:锁住类对象(Class)。
  • 同步代码块:可以锁定特定对象,提高并发性。
public void method() {synchronized (this) {// 代码块}
}

2.3 synchronized 的特性

  • 可重入性:一个线程获取锁后可以多次进入同步代码。
  • 不可中断:线程获取锁后,其他线程只能等待。
  • JVM 层面实现:使用 monitorentermonitorexit 指令。

3. Lock 接口(显式锁)

Lock 接口提供比 synchronized 更灵活的锁控制,主要实现类是 ReentrantLock

3.1 ReentrantLock 用法

import java.util.concurrent.locks.ReentrantLock;public class LockExample {private final ReentrantLock lock = new ReentrantLock();private int count = 0;public void increment() {lock.lock();try {count++;} finally {lock.unlock();}}
}

3.2 ReentrantLock 特性

  • 可重入性:和 synchronized 类似,一个线程可以多次获得相同的锁。
  • 可中断:支持 lockInterruptibly() 方法,中断等待锁的线程。
  • 公平锁和非公平锁:默认非公平锁,可选择公平锁保证线程按请求顺序获取锁。
ReentrantLock fairLock = new ReentrantLock(true); // 公平锁

4. ReadWriteLock(读写锁)

ReadWriteLock 提供读锁(多个线程可读)和写锁(独占)。

import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLockExample {private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();private int data = 0;public int read() {lock.readLock().lock();try {return data;} finally {lock.readLock().unlock();}}public void write(int value) {lock.writeLock().lock();try {data = value;} finally {lock.writeLock().unlock();}}
}

5. 乐观锁与悲观锁

5.1 悲观锁

认为竞争严重,每次访问资源都加锁(synchronizedLock)。

5.2 乐观锁

认为竞争较少,使用 CAS(Compare And Swap) 机制,比如 AtomicInteger

import java.util.concurrent.atomic.AtomicInteger;public class AtomicExample {private final AtomicInteger count = new AtomicInteger(0);public void increment() {count.incrementAndGet();}
}

6. StampedLock(改进的读写锁)

StampedLock 提供乐观读锁,提高并发性能。

import java.util.concurrent.locks.StampedLock;public class StampedLockExample {private final StampedLock lock = new StampedLock();private int data = 0;public int read() {long stamp = lock.tryOptimisticRead();int currentData = data;if (!lock.validate(stamp)) { // 检测数据是否被修改lock.readLock();try {currentData = data;} finally {lock.unlockRead(stamp);}}return currentData;}
}

7. ThreadLocal 变量

ThreadLocal 不是锁,而是让每个线程拥有自己的变量副本,避免锁竞争。

public class ThreadLocalExample {private static final ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);public void increment() {threadLocal.set(threadLocal.get() + 1);}
}

8. 选择合适的锁

锁类型特性适用场景
synchronizedJVM 层面,简单易用适合简单同步需求
ReentrantLock可中断、支持公平锁适合需要高级控制的场景
ReadWriteLock读写分离,提高并发读多写少的情况
StampedLock乐观读,提高性能适合高并发读的场景
ThreadLocal线程私有,无锁线程隔离数据

9. 总结

Java 提供了多种锁机制,每种锁都有其适用场景。synchronized 适用于简单同步,Lock 提供更多控制,ReadWriteLock 适用于读多写少的情况,StampedLock 提供乐观读锁以提高并发性能。此外,ThreadLocal 可用于无锁并发,避免数据竞争。

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

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

相关文章

JavaScript 中 “new Map()”的使用

new Map() 是 JavaScript 中用于创建 Map 对象 的构造函数。Map 是一种键值对集合&#xff0c;类似于普通对象&#xff08;Object&#xff09;&#xff0c;但有以下区别&#xff1a; 1. Map 的特点 1.1 键的类型 Map&#xff1a;键可以是任意类型&#xff08;包括对象、函数、…

Rust语言的集成测试

Rust语言的集成测试 引言 随着软件开发的不断发展&#xff0c;测试已成为一个不可或缺的环节。特别是在系统复杂度日益增加的今天&#xff0c;确保代码质量和稳定性变得尤为重要。Rust作为一门强调安全性和性能的编程语言&#xff0c;其测试框架提供了丰富的工具来帮助开发者…

手写简单的Spring基于注解配置的程序

需求说明&#xff1a; 自己写一个简单的 Spring 容器, 通过读取类的注解(Component ControllerService Reponsitory) &#xff0c;将对象注入到 IOC 容器&#xff0c;自己使用 IOAnnotaion反射集合 技术实现 思路分析&#xff1a; 一、新建一个包component并在包下创建bean类 …

WSL 导入完整系统包教程

作者&#xff1a; DWDROME 配置环境&#xff1a; OS: Ubuntu 20.04.6 LTS on Windows 11 x86_64Kernel: 5.15.167.4-microsoft-standard-WSL2ros-noetic &#x1f9ed;WSL 导入完整系统包教程 ✅ 一、准备导出文件 假设你已有一个 .tar 的完整系统包&#xff08;如从 WSL 或 L…

使用selenium来获取数据集

使用selenium来获取数据集 1、下载最新的chrome浏览器与chromedriver.exe 查看chrome的版本,打开谷歌浏览器,点击右上角的三个点,然后点击【帮助】, 点击【关于Google Chrome】 然后去下载同样为134版本号的chromedriver.exe, 网址:https://googlechromelabs.github.…

(二)VMware:VMware虚拟机安装CentOS教程

目录 1、准备CentOS 7镜像1.1、官网镜像下载1.2、清华大学开源镜像下载​1.3、阿里云开源镜像下载 2、使用 VMware安装CentOS 72.1、创建虚拟机2.2、选择自定义安装2.3、硬件兼容性&#xff0c;保持默认2.4、选择下载的ISO镜像2.5、设置虚拟机名称以及存放磁盘位置2.6、按照需求…

【Agent】Dify Docker 安装问题 INTERNAL SERVER ERROR

总结&#xff1a;建议大家选择稳定版本的分支&#xff0c;直接拉取 master 分支&#xff0c;可能出现一下后面更新代码导致缺失一些环境内容。 启动报错 一直停留在 INSTALL 界面 我是通过 Docker 进行安装的&#xff0c;由于项目开发者不严谨导致&#xff0c;遇到一个奇怪的…

MySQL -- 复合查询

数据库的查询是数据库使用中比较重要的环节&#xff0c;前面的基础查询比较简单&#xff0c;不做介绍&#xff0c;可自行查阅。本文主要介绍复合查询&#xff0c;并结合用例进行讲解。 本文的用例依据Soctt模式的经典测试表&#xff0c;可以自行下载&#xff0c;也可以自己创建…

flutter 开发web端的性能优化

参考资料 Flutter for Web 首次首屏优化 ——JS 分片优化_main.dart.js-CSDN博客文章浏览阅读1.4k次。本文介绍了如何通过延迟加载组件和js分片优化Flutter for Web应用的加载速度。在实践中&#xff0c;通过按需加载减少js文件大小&#xff0c;使用并行加载提升加载效率。通过…

编译安装redis,systemtcl配置redis自启动,系统并发调优

编译安装redis&#xff0c;systemtcl配置redis自启动&#xff0c;系统并发调优 1、编译安装redis wget https://download.redis.io/releases/redis-7.4.2.tar.gz tar -zxf redis-7.4.2.tar.gz cd redis-7.4.2/ make make install/usr/local/bin/redis-server -v2、systemtcl配…

firefly经典蓝牙和QProcess、QFileSystemWatcher记录

QProcess 默认不会启动一个 shell 来解析命令,而是直接调用操作系统的系统调用来启动外部程序。也就是通过fork一个子线程或者exec一个子进程来执行命令。 QProcess的参数模式 QProcess 需要明确指定命令的可执行文件路径或参数列表。 如果命令是一个可执行文件的路径…

Java定时任务的三重境界:从单机心跳到分布式协调

《Java定时任务的三重境界&#xff1a;从单机心跳到分布式协调》 本文将以生产级代码标准&#xff0c;揭秘Java定时任务从基础API到分布式调度的6种实现范式&#xff0c;深入剖析ScheduledThreadPoolExecutor与Quartz Scheduler的线程模型差异&#xff0c;并给出各方案的性能压…

QT QML实现音频波形图进度条,可点击定位或拖动进度

前言 本项目实现了使用QT QML创建一个音频波形图进度条的功能。用户可以在界面上看到音频波形图&#xff0c;并且可以点击进度条上的位置进行定位&#xff0c;也可以拖动进度条来调整播放进度。可以让用户更方便地控制音频的播放进度&#xff0c;并且通过音频波形图可以直观地…

高速网络包处理,基础网络协议上内核态直接处理数据包,XDP技术的原理

文章目录 预备知识TCP/IP 网络模型&#xff08;4层、7层&#xff09;iptables/netfilterlinux网络为什么慢 DPDKXDPBFPeBPFXDPXDP 程序典型执行流通过网络协议栈的入包XDP 组成 使用 GO 编写 XDP 程序明确流程选择eBPF库编写eBPF代码编写Go代码动态更新黑名单 预备知识 TCP/IP…

[每周一更]-(第137期):Go + Gin 实战:Docker Compose + Apache 反向代理全流程

文章目录 **1. Go 代码示例&#xff08;main.go&#xff09;****2. Dockerfile 多段构建**3.构建 Docker 镜像**4. docker-compose.yml 直接拉取镜像****5. 运行容器****6. 测试 API**7、配置域名访问**DNS解析&#xff1a;将域名转换为IP地址****DNS寻址示例** 8.错误记录 访问…

SpringMVC基本使用

SpringMVC是什么&#xff1f; Spring MVC 是 Spring 框架中的一个模块&#xff0c;用于构建基于 MVC&#xff08;Model-View-Controller&#xff09;设计模式的 Web 应用程序。它分离了应用程序的业务逻辑、用户界面和用户输入&#xff0c;使开发更加模块化和易于维护。 核心…

Qt之MVC架构MVD

什么是MVC架构&#xff1a; MVC模式&#xff08;Model–view–controller&#xff09;是软件工程中的一种软件架构模式&#xff0c;把软件系统分为三个基本部分&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controll…

Stream 流中 flatMap 方法详解

&#x1f3af; 1. flatMap() 到底是啥&#xff1f; flatMap() 是 Stream 里的中间操作&#xff0c;它的作用可以分两步理解&#xff1a; 第一步&#xff1a;对流里的每个元素&#xff0c;先**映射&#xff08;转换&#xff09;**成一个 Stream。第二步&#xff1a;把多个子流…

(C语言)理解 回调函数 和 qsort函数

一. 回调函数 1. 什么是回调函数&#xff1f; 回调函数&#xff08;Callback Function&#xff09;是通过 函数指针 调用的函数。其本质是&#xff1a; 将函数作为参数传递给另一个函数&#xff0c;并在特定条件下被调用&#xff0c;实现 反向控制。 2. 回调函数的使用 回调函…

vscode记录

vs code 下载安装&#xff0c;git 配置&#xff0c;插件安装_vscode安装git插件-CSDN博客 手把手教你在VS Code中使用 Git_vscode如何输入git命令-CSDN博客 VS Code | 如何快速重启VS Code&#xff1f;_vscode 怎么一键全部重启-CSDN博客 1&#xff0c;安装插件与git集成 2&am…