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

中国银行建设网站首页上海自贸区注册公司在哪里

中国银行建设网站首页,上海自贸区注册公司在哪里,无锡有多少家公司,企业门户首页一、核心概念分类与对比首先通过一张表总结四类锁的关键区别:锁类型核心思想实现方式(典型工具)适用场景优点缺点​悲观锁​假设并发冲突一定会发生,访问数据前先加锁,阻止其他线程/事务同时修改Java:synch…

一、核心概念分类与对比

首先通过一张表总结四类锁的关键区别:

锁类型核心思想实现方式(典型工具)适用场景优点缺点
悲观锁假设并发冲突一定会发生,访问数据前先加锁,阻止其他线程/事务同时修改Java:synchronizedReentrantLock;数据库:SELECT ... FOR UPDATE写多读少、冲突概率高的场景(如库存扣减、账户余额更新)强一致性,实现简单性能开销大(阻塞等待),可能死锁
乐观锁假设并发冲突不常发生,不加锁直接操作,提交时检查数据是否被其他线程/事务修改过Java:AtomicInteger(CAS)、版本号机制(如version字段);数据库:版本号或时间戳读多写少、冲突概率低的场景(如商品浏览量统计、CMS内容更新)无阻塞,性能高需处理冲突重试,ABA问题需额外解决
隐式锁锁的获取和释放由系统/框架自动管理,开发者无需显式编写加锁/解锁代码Java:synchronized(JVM自动加锁/释放)、数据库:行锁(如InnoDB自动加锁)简单同步场景(如单方法内的线程安全控制、数据库的单行操作)代码简洁,不易遗漏灵活性低,控制粒度粗
显式锁开发者需要手动调用API获取锁和释放锁,通常提供更丰富的功能(如超时、可中断)Java:ReentrantLockReadWriteLock;数据库:部分分布式锁需手动控制加锁逻辑需要精细控制锁行为(如超时获取、公平锁、多条件队列)的场景功能灵活,可定制化代码复杂度高,需手动释放避免死锁

二、详细解析每类锁

1. 悲观锁(Pessimistic Lock)

核心思想

​“先加锁,再访问”​​ —— 认为并发冲突一定会发生,因此在操作数据前先获取锁,确保同一时间只有一个线程/事务能修改数据,其他线程/事务必须等待锁释放。

实现方式
  • Java层面​:

    • synchronized 关键字(JVM内置悲观锁,自动管理锁的获取与释放)。
    • ReentrantLock(显式锁,需手动调用lock()unlock(),支持超时、可中断等高级功能)。
  • 数据库层面​:

    • ​**SELECT ... FOR UPDATE**​:对查询的行记录加排他锁(其他事务无法修改或加锁,直到当前事务提交或回滚)。
      -- 事务1:对id=1的商品库存加锁
      BEGIN;
      SELECT stock FROM products WHERE id = 1 FOR UPDATE; -- 加排他锁
      UPDATE products SET stock = stock - 1 WHERE id = 1; -- 安全扣减
      COMMIT;
    • 行锁/表锁​:InnoDB引擎默认对索引列加行锁(若无索引可能升级为表锁),MyISAM仅支持表锁。
典型场景
  • 写多读少​:如秒杀库存扣减、银行账户余额转账(冲突概率高,需强一致性)。
  • 事务性操作​:数据库的多语句事务中保证数据修改的原子性(如订单创建+库存扣减)。
优缺点
  • 优点​:实现简单,保证强一致性(不会出现脏写)。
  • 缺点​:性能开销大(线程/事务阻塞等待),可能引发死锁(多个线程互相持有对方需要的锁)。

2. 乐观锁(Optimistic Lock)

核心思想

​“先操作,再检查”​​ —— 认为并发冲突不常发生,因此直接读取并修改数据,提交时通过版本号或CAS机制检查数据是否被其他线程/事务修改过,若冲突则重试或失败。

实现方式
  • Java层面​:

    • CAS(Compare-And-Swap)​​:通过AtomicIntegerAtomicLong等原子类的底层CAS指令(如Unsafe.compareAndSwapInt)实现无锁并发。
      AtomicInteger stock = new AtomicInteger(100);
      // 尝试扣减库存(CAS保证原子性)
      boolean success = stock.compareAndSet(100, 99); // 当前值为100时才更新为99
    • 版本号机制​:在数据表中增加version字段,更新时检查版本是否匹配(类似CAS)。
      // 伪代码:更新商品信息时检查版本
      int oldVersion = product.getVersion();
      int affectedRows = update("UPDATE products SET name=?, version=version+1 WHERE id=? AND version=?", newName, productId, oldVersion);
      if (affectedRows == 0) {throw new OptimisticLockException("数据已被其他事务修改,请重试");
      }
  • 数据库层面​:

    • 版本号字段​:表中增加version列(每次更新自增),事务提交时通过WHERE version=旧值校验。
    • 时间戳字段​:用update_time代替版本号(精度依赖数据库时间)。
典型场景
  • 读多写少​:如商品浏览量统计(频繁读取,偶尔更新)、CMS内容编辑(多人协作但冲突概率低)。
  • 高并发但冲突少的场景​:如用户信息更新(大部分请求不冲突,少数冲突时重试成本可接受)。
优缺点
  • 优点​:无阻塞,性能高(不占用锁资源);适合分布式环境(如Redis的乐观锁通过WATCH命令实现)。
  • 缺点​:需处理冲突重试(可能引发死循环),存在ABA问题(CAS中值从A→B→A,CAS无法感知中间变化,需用版本号或时间戳解决)。

3. 隐式锁(Implicit Lock)

核心思想

​“自动管理”​​ —— 锁的获取和释放由系统/运行时环境(如JVM、数据库引擎)自动完成,开发者无需显式编写加锁或解锁代码。

实现方式
  • Java层面​:

    • synchronized 关键字:进入同步代码块时JVM自动加锁(通过对象监视器Monitor),退出时(正常return或异常抛出)自动释放锁。
      public synchronized void safeMethod() {// 进入方法时JVM自动加锁,退出时自动释放
      }
  • 数据库层面​:

    • 行锁/表锁​:InnoDB引擎在执行更新/删除操作时,若条件命中索引,会自动对相关行加锁(开发者无需手动写FOR UPDATE,但需理解其隐式行为)。
      -- 隐式加行锁:更新id=1的记录时,InnoDB自动对id=1的行加排他锁
      UPDATE products SET stock = stock - 1 WHERE id = 1;
典型场景
  • 简单同步需求​:单方法内的线程安全控制(如工具类的单例初始化)。
  • 数据库的单语句操作​:单条更新/删除语句(依赖索引时自动加行锁)。
优缺点
  • 优点​:代码简洁,不易遗漏锁释放(避免死锁)。
  • 缺点​:控制粒度粗(如synchronized锁住整个方法可能影响性能),灵活性低(无法定制超时、公平性等)。

4. 显式锁(Explicit Lock)

核心思想

​“手动管理”​​ —— 开发者需要显式调用API获取锁和释放锁,通常提供更丰富的功能(如超时等待、可中断、公平锁、多条件队列)。

实现方式
  • Java层面​:

    • ReentrantLock(可重入显式锁):需手动调用lock()unlock()(通常配合try-finally确保释放)。
      ReentrantLock lock = new ReentrantLock();
      lock.lock(); // 手动加锁
      try {// 临界区代码
      } finally {lock.unlock(); // 必须手动释放!
      }
    • 高级功能​:支持超时获取锁(tryLock(long timeout, TimeUnit unit))、可中断锁(lockInterruptibly())、公平锁(构造参数fair=true)、多个条件变量(Condition)。
  • 数据库层面​:

    • 部分分布式锁(如基于Redis的Redlock算法)需开发者手动控制多节点加锁逻辑(非标准SQL功能)。
典型场景
  • 需要精细控制锁行为​:如限制锁等待时间(避免线程长时间阻塞)、公平性要求(按请求顺序获取锁)、多条件等待(如生产者-消费者模型中的不同队列)。
  • 复杂并发逻辑​:多个线程协作时(如线程池任务调度、资源池管理)。
优缺点
  • 优点​:功能灵活(支持超时、中断、公平性),可定制化程度高。
  • 缺点​:代码复杂度高(需手动释放锁,否则可能死锁),对开发者要求更高。

三、面试常见问题扩展

Q1:synchronized 是悲观锁还是乐观锁?是隐式锁还是显式锁?

  • 答案​:synchronized 是悲观锁​(假设冲突会发生,先加锁再访问),同时也是隐式锁​(锁的获取和释放由JVM自动管理,开发者无需手动操作)。

Q2:乐观锁一定比悲观锁性能好吗?

  • 答案​:不一定!乐观锁在冲突概率低时性能更高(无阻塞),但在冲突频繁时因重试次数增加可能导致整体性能下降;悲观锁在冲突高时能直接避免竞争,但会阻塞其他线程。需根据业务场景选择。

Q3:数据库的乐观锁如何避免ABA问题?

  • 答案​:通过版本号(version)​而非数据本身值来判断变化。每次更新时版本号+1,即使数据的值从A→B→A,版本号也会递增(如1→2→3),通过检查版本号是否匹配可感知中间修改。

Q4:Redis分布式锁是悲观锁还是乐观锁?

  • 答案​:Redis分布式锁本质是悲观锁​(通过SET key value NX PX timeout加锁后,其他客户端无法同时获取同一把锁),但它是基于Redis的乐观锁思想(如WATCH命令监控键变化)的扩展应用。

四、总结表格(快速回顾)

锁类型思想实现方式(Java示例)典型场景核心特点
悲观锁先加锁再访问synchronizedReentrantLockSELECT ... FOR UPDATE写多读少、强一致性需求强一致,可能阻塞/死锁
乐观锁先操作后检查AtomicInteger(CAS)、版本号机制读多写少、低冲突场景无阻塞,需处理冲突重试
隐式锁自动管理synchronized(JVM自动加锁)、数据库隐式行锁简单同步、单语句操作代码简洁,控制粒度粗
显式锁手动管理ReentrantLock、分布式锁手动控制复杂并发逻辑、精细控制需求功能灵活,需手动释放

掌握这些锁的核心逻辑,不仅能应对秋招面试中的高频问题(如“synchronized和ReentrantLock的区别”“乐观锁如何实现”“分布式锁的选型”),还能在实际开发中根据业务场景选择最合适的并发控制策略。建议结合代码Demo(如用CAS实现计数器、用synchronized保护共享资源)加深理解!

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

相关文章:

  • 开源隐私计算框架SecretFlow | 基于隐语的金融全链路场景介绍和应用实践
  • 【20】MFC入门到精通——MFC 运行或调试状态在 VS输出框,打印字符串信息 OutputDebugString(str);
  • 唐山cms模板建站南昌网站优化
  • 年化454.23%,最大回撤6.97%,加上了每笔订单的交易细节,系统及策略代码已发布
  • 企业招聘新趋势:「AI面试」如何破解在线作弊难题?
  • 人工智能风险与伦理(1)
  • 做网站能赚到钱吗深圳优化怎么做搜索
  • 怎么编辑网站甘肃住房城乡建设厅网站
  • 【仓颉语言】原生智能、全场景与强安全的设计哲学
  • vue使用d3实现图片的缩放、拖动、添加/删除标记等功能
  • 云南建站专业网站建设模块
  • 心悦dnf免做卡网站淘宝客网站如何做
  • ROS 学习
  • 《信息系统项目管理师》案例分析题及解析模拟题3
  • 深圳网络科技公司排名10深圳网站优化企业
  • 开发一个企业网站需要多少钱杭州 城西 做网站
  • 宁夏建设厅网站领导怎么做网站关键词库排名
  • 企业网站备案流程品牌建设措施
  • 北京网站优化体验软件技术专业介绍
  • 【Windows10】开机自启VMware workstation16
  • 功能型网站建设时间哈尔滨做平台网站平台公司哪家好
  • 基于改进UNet的脑电信号去噪方法研究
  • 中企动力 35 做网站flash网站尺寸
  • 番禺区网站建设哪里有网页设计与制作报告书
  • Linux-权限与开发工具
  • 网站空间多大wordpress更换主机
  • 重庆潼南网站建设全球华设计大奖
  • linux学习笔记(51)Redis发布订阅 主从复制 缓存 雪崩
  • 品牌建设助力高质量发展seo排名是什么意思
  • 软考 系统架构设计师系列知识点之杂项集萃(178)