详谈 乐观锁 悲观锁

本文详细介绍了乐观锁和悲观锁的概念,解释了它们的工作原理和适用场景。悲观锁在多线程环境中确保共享资源每次只被一个线程使用,而乐观锁则假设并发情况下很少发生冲突,主要通过版本号机制和CAS算法来防止数据不一致。乐观锁适合读多写少的场景,以提高系统吞吐量,而悲观锁在多写场景下更为适用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

望文生义,乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定是好是坏。

悲观锁

共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程。关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

白话理解:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁


乐观锁

每次去拿数据的时候都认为其他进程不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别进程有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量。如:处理扣款、库存等场景都会应用此方式的锁。

使用场景

乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。

但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。

乐观锁实现方式

乐观锁一般会使用版本号机制或CAS算法实现,下面对两种方式分别进行介绍

版本号机制

一般是在数据表中加上一个数据版本号ver字段,表示数据被修改的次数,当数据被修改时,ver值会加1。当线程A要更新数据值时,在读取数据的同时也会读取ver值,在提交更新时,若刚才读取到的ver值为当前数据库中的ver值相等时才更新,否则重试更新操作,直到更新成功。

举一个简单的例子: 数据库中产品X库存信息表中有一个 ver 字段,当前值为 1,而产品X 库存为 9

  1. 操作员 A 进行发货处理,会从库中取得产品 X ver = 1,并从库存中 9-5
  2. 在操作员 A 发货过程中,操作员 B 也进行发货操作 从库中取得产品 X ver = 1,并从库存中 9-6
  3. 操作员 A 完成了发货工作,将数据版本号( ver=1 ),连产品库存扣除后( 4 ),提交至数据库更新,此时由于提交数据版本等于数据库记录当前版本,数据被更新,数据库记录 version 更新为 2 。
  4. 操作员 B 完成后,也将版本号( ver=1 )试图向数据库提交数据( 3 ),但此时比对数据库记录版本时发现,操作员 B 提交的数据版本号为 1 ,数据库记录当前版本也为 2 ,不满足 “ 提交版本必须等于当前版本才能执行更新 “ 的乐观锁策略,因此,操作员 B 的提交被驳回。
    5

这样,就避免了操作员 B 用基于 ver=1 的旧数据修改的结果覆盖操作员A 的操作结果的可能

CAS(比较并交换)

CAS 有 3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

V 可以理解为当前版本号
A 初次读取的版本号,与内存V对比
B 操作成功是更新的版本号

### PLC的详细解析 #### 工作原理 可编程逻辑控制器(PLC)是一种专为工业环境设计的数字计算机,用于自动化控制。其核心工作原理基于循环扫描的方式执行用户程序。在每次扫描周期中,PLC会完成输入采样、程序执行和输出刷新三个阶段[^1]。 - **输入采样**:PLC取所有输入信号的状态,并将这些状态存储到输入映像寄存器中。 - **程序执行**:根据输入映像寄存器中的数据,按照用户编写的程序进行逻辑运算或算术运算。 - **输出刷新**:将程序执行的结果写入输出锁存器,从而改变外部设备的状态。 这种循环扫描机制确保了PLC能够实时响应外部事件并作出相应的控制动作。 #### 应用场景 PLC广泛应用于各种工业自动化领域,包括但不限于: - **制造业**:如汽车装配线、食品加工生产线等,用于控制机械臂、传送带以及其他生产机械。 - **过程控制**:在化工、石油精炼等行业中,用来监控和调节温度、压力、流量等参数。 - **楼宇自动化**:用于暖通空调系统(HVAC)、电梯控制系统以及安全系统等。 - **能源管理**:在电力分配系统中实现负载平衡和故障检测等功能。 #### 编程方法 PLC的编程通常采用几种标准化语言,最常见的是梯形图(Ladder Diagram, LD)、功能块图(Function Block Diagram, FBD)、结构化文本(Structured Text, ST)和指令列表(Instruction List, IL)。每种语言都有其特点和适用场合。 - **梯形图**是最直观的一种图形化编程语言,它模仿继电器逻辑电路的设计方式,易于理解和学习。 - **功能块图**允许开发者使用预定义的功能块来构建复杂的控制逻辑,支持模块化设计。 - **结构化文本**是一种高级文本编程语言,适合处理复杂的数据操作和算法实现。 - **指令列表**类似于汇编语言,提供了对硬件直接访问的能力,但相对难以编写和维护。 下面是一个简单的梯形图示例,展示了如何通过两个按钮控制一个指示灯: ```plaintext |----[ ]----( )--| I0.0 Q0.0 |----[ ]----( )--| I0.1 Q0.0 ``` 在这个例子中,如果任一按钮(I0.0 或 I0.1)被按下,则指示灯(Q0.0)会被点亮。 此外,现代PLC还支持更复杂的编程技术,比如面向对象的方法,其中可以创建可重用的功能块(FBs),例如`FB_RobotCtrl`、`FB_Vision` 和 `FB_Safety`,它们分别用于机器人控制、视觉通信处理和安全联锁逻辑。全局数据块(如`DATA_DB.gxw`)则用来保存配方信息和运行时参数,使得不同功能块之间能够共享数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸟厚非

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值