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

JAVA锁机制

    Java中的锁机制是并发编程的核心,用于解决多线程共享资源竞争问题,保证线程安全。

基本概念

    在并发场景中,多个线程同时操作共享资源时,可能导致数据不一致(脏读、丢失更新)。锁的作用是通过控制线程对资源的访问权限,确保同一时间只有特定的线程能操作资源,从而保证线程安全。

锁的核心特性:

  • 互斥性:同一时间只有一个线程能持有锁,其他线程需等待;
  • 可见性:线程释放锁时,其修改的共享资源会刷新到主内存;线程获取锁时,会从主内存加载最新的资源;
  • 可重入性:线程可重复获取已持有的锁(避免死锁);

锁的分类

按锁的状态分类

偏向锁:

  • 适应于只有一个线程访问同步块的场景;
  • 第一次获取锁时,将线程ID记录在对象头中;
  • 后续该线程再次获取锁时无需进行同步操作;

轻量级锁:

  • 多个线程交替执行同步块,不存在竞争的情况下使用;
  • 通过CAS操作和自旋实现

重量级锁:

  • 当存在多个线程竞争锁时使用;
  • 线程阻塞和唤醒需要操作系统介入,开销大;

按锁的竞争机制分类

乐观锁:

  • 认为数据一般不会发生冲突;
  • 使用CAS操作实现;
  • 如AtomicInteger等原子类;
  • 适用于冲突较少的场景;

悲观锁:

  • 认为数据会发生冲突;
  • 整个数据处理过程中锁定数据;
  • 适用于冲突较多的场景;

按公平性分类

公平锁:

  • 线程获取锁的顺序与请求顺序一致,无插队现象;
  • 公平性高,开销较大,性能较低;

非公平锁:

  • 线程获取锁的顺序不保证与请求顺序一致,允许新线程插队;
  • 性能较高,可能导致部分线程饥饿;

按锁的共享性分类

独占锁(排他锁):

  • 同一时间只有一个线程持有锁,其他线程必须等待。
  • 适应场景:写操作

共享锁:

  • 允许多个线程同时持有锁,仅限制写操作。
  • 适应场景:读操作。

锁的核心问题与解决

死锁:

多个线程互相等待对方释放而进入无限阻塞

  • 固定锁获取顺序,使用tryLock设置超时,短期释放锁。

活锁:

线程不断尝试获取锁,但因某种条件始终失败

  • 引入随机等待时间,打破重试顺序。

饥饿:

低优先级线程长期无法获取锁

  • 使用公平锁,控制优先级

锁的实现

synchronized

    synchronized是基于对象监视器实现的。每个java对象都有一个与之关联的监视器,当线程进入synchronized代码块时,它会尝试获取对象的监视器锁。如果获取成功,线程可以执行同步代码块;如果获取失败,线程会被阻塞,直到锁释放。

public class Demo {private int i = 0;//同步方法public synchronized void addI(){i++;}//同步代码块public void addJ(){synchronized(this){i++;}}public int getI() {return i;}public void reset() {i = 0;}
}

ReentrantLock

    ReentrantLock。多个线程可以多次获取同意把锁,可以选择公平锁或非公平锁;可以设置获取锁的超时时间,支持多个条件变量。

核心方法:

  • lock():获取锁(获取到则阻塞);
  • trylock():尝试获取锁(立刻返回true或false,避免死锁);
  • unlock():释放锁(必须在finally中使用,比避免死锁);
  • newCondition():创建条件变量,用于线程间通信。
public class ReentrantLockExample {private int count = 0;private final ReentrantLock lock = new ReentrantLock();private final Condition condition = lock.newCondition();// 基本的锁操作public void increment() {lock.lock();try {count++;} finally {lock.unlock();}}// 可中断的锁操作public void interruptibleIncrement() throws InterruptedException {lock.lockInterruptibly();try {count++;} finally {lock.unlock();}}// 带超时的锁操作public boolean tryIncrement(int timeoutMs) throws InterruptedException {if (lock.tryLock(timeoutMs, java.util.concurrent.TimeUnit.MILLISECONDS)) {try {count++;return true;} finally {lock.unlock();}}return false;}// 非阻塞尝试获取锁public boolean tryIncrementOnce() {if (lock.tryLock()) {try {count++;return true;} finally {lock.unlock();}}return false;}// 等待条件public void waitForCondition() throws InterruptedException {lock.lock();try {condition.await();} finally {lock.unlock();}}// 发送信号public void signal() {lock.lock();try {condition.signal();} finally {lock.unlock();}}public int getCount() {return count;}public void reset() {count = 0;}public boolean isLocked() {return lock.isLocked();}public boolean hasQueuedThreads() {return lock.hasQueuedThreads();}
}

ReentrantReadWriteLock

    一种读写分离锁,允许多个读线程同时访问,但写线程与读线程,写线程与写线程互斥。适合读多写少的场景,提升并发效率。

public class ReentrantReadWriteLockExample {private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();private final ReentrantReadWriteLock.ReadLock readLock = lock.readLock();private final ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();private String data;public String read() {readLock.lock();try {return data;} finally {readLock.unlock();}}public void write(String newData) {writeLock.lock();try {data = newData;} finally {writeLock.unlock();}}
}

StampedLock

    StampedLock是java8新引入的一种锁,提供了比读写锁更好的性能。

三种模式:

  • 写锁(独占):获取戳记,释放时许传入戳记。
  • 读锁(共享):与ReentrantReadWriteLock的读锁类似。
  • 乐观读:无锁状态读取,验证数据是否被修改。
    public void move(double deltaX, double deltaY) {long stamp = lock.writeLock();try {x += deltaX;y += deltaY;} finally {lock.unlockWrite(stamp);}}// 乐观读public double distanceFromOrigin() {long stamp = lock.tryOptimisticRead();double currentX = x, currentY = y;if (!lock.validate(stamp)) {// 乐观读失败,升级为悲观读stamp = lock.readLock();try {currentX = x;currentY = y;} finally {lock.unlockRead(stamp);}}return Math.sqrt(currentX * currentX + currentY * currentY);}
}

锁的选择

类型特点适应场景
synchronizedJVM内置,自动释放,可重入简单同步场景
ReentrantLock可中断,可现时,公平锁更精细的控制场景
ReadWriteLock读写分离,提高并发能力读多写少的场景
StampedLock支持乐观读,高性能高并发读多写少场景

http://www.dtcms.com/a/428597.html

相关文章:

  • 免费素材库网站怎么用id导入wordpress
  • 【开发日记】LLM开发中的一些参数设置
  • 莆田网站建设平台推广联盟
  • 双抗 ADC 设计的核心密码:从抗体机制与结构看 “精准杀伤” 的底层逻辑
  • 网络销售网站设置购物网站的建设时间
  • 山东城市建设厅网站龙岩论坛
  • 阿里巴巴网站图片如何做白长沙网站建站公司
  • JAVA学习笔记——9道综合练习习题+二维数组
  • 微信编辑器做网站长沙网站开发公司
  • 网站备案信息代码wordpress高亮代码转义
  • 企业响应式网站建设报价网站如何做浏览量
  • 个体工商户可以申请网站建设吗长沙市师德师风建设网站
  • 青海网站建设设计江苏省建筑工程集团有限公司
  • 广东建设行业招聘 什么网站google广告联盟网站
  • dw做网站一般是多大的尺寸医院网站icp备案吗
  • 郑州 网站制作网站运营的案例
  • 学校网站代码模板网站建设平台安全问题有哪些方面
  • ubuntu开启NFS网络文件共享服务,并使用windows访问及排错过程
  • WinForm仪表盘
  • 做网站找酷万体育器材网站模板
  • 如何免费做公司网站wordpress模板带后台
  • Linux日志查看常用命令
  • 泰安整站优化wordpress头部空白
  • 考研408之栈与队列学习
  • 软考-系统架构设计师 软件架构概念详细讲解
  • 都匀网站建设住建部注册中心官网
  • Problem: lab-week4- exercise02 Quick sort
  • 营销型网站策划怎么做中国公司查询网站
  • 通信领域常见基本概念与术语
  • Trae CN配置Maven环境