乐观锁与悲观锁
乐观锁
乐观锁是一种并发控制的机制,其核心思想是假设多个事务之间的冲突是不太可能发生的,因此在事务处理之前不会加锁,而是在事务提交的时候再检查是否有冲突。如果发现冲突,就会回滚事务,重新尝试。
实现乐观锁的方式
1. 版本号机制:
- 每个数据记录都关联一个版本号,当读取数据时,将版本号一同读出。在更新数据时,只有当版本号匹配时才能执行更新操作,否则认为是冲突,需要进行回滚或其他处理。
- 适用于数据库表中的记录,常用于数据库乐观锁实现。
2. 时间戳(Timestamp)机制:
- 每个事务执行时都记录一个时间戳,更新数据时带上时间戳。当提交时,检查时间戳,如果发现其他事务已经更新了数据,就认为发生了冲突。
- 可以在数据库中记录事务的开始时间作为时间戳,也可以使用递增的整数作为版本号。
3. CAS(Compare and Swap)操作:
- 使用原子性的CAS操作来判断是否发生冲突。在Java中,
Atomic
类提供了一些原子操作,如compareAndSet
。 - 适用于基于内存的数据结构,如Java中的
AtomicInteger
、AtomicLong
等。
乐观锁的优点
-
性能好: 在低并发环境下,乐观锁的性能通常优于悲观锁,因为不需要额外的加锁和解锁操作。
-
无阻塞: 由于乐观锁不会一开始就阻塞线程,因此适用于读操作较频繁、写操作较少的场景。
乐观锁的缺点
-
冲突处理: 当多个事务发生冲突时,需要进行冲突处理,通常是通过回滚事务,重新尝试。
-
不适用于高并发写操作: 当写操作较频繁时,乐观锁的性能可能下降,因为不断的冲突会导致事务的回滚和重试。
-
无法解决所有并发问题: 乐观锁机制不能解决所有并发问题,特别是在一些复杂的业务场景中。
使用乐观锁的示例(基于版本号机制):
class Account {private String accountId;private double balance;private long version; // 版本号// 省略其他代码// 更新余额的方法public void updateBalance(double amount) {// 模拟乐观锁检查if (version != getAccountVersionFromDatabase()) {throw new OptimisticLockException("Concurrent modification detected");}// 更新余额this.balance += amount;// 更新版本号version++;// 更新数据库中的版本号和余额updateAccountInDatabase();}
}
version
是账户对象的版本号,每次更新时都需要检查数据库中的版本号是否一致,如果不一致,则抛出乐观锁异常。
悲观锁
悲观锁是一种并发控制的机制,它的核心思想是在操作数据之前,悲观地认为会有并发操作的冲突,因此先进行加锁,确保每个时刻只有一个事务可以访问或修改共享资源。这种锁定机制确保了数据的一致性,但也可能导致性能的下降,因为多个事务可能需要等待锁的释放。
悲观锁的实现方式主要包括数据库锁、行级锁、表级锁等,以及编程语言级别的锁,如Java中的synchronized关键字、数据库中的SELECT ... FOR UPDATE等。
实现悲观锁的方式
1. 数据库锁:
- 行级锁(Row-level lock): 在数据库中锁定表中的某一行,确保只有一个事务可以修改这一行的数据。例如,在SQL中可以使用
FOR UPDATE
语句。 - 表级锁(Table-level lock): 锁定整个表,防止其他事务访问该表中的任何数据。
2. 编程语言级别的锁:
- 在编程语言中,通过关键字实现锁机制。例如,Java中的
synchronized
关键字用于同步方法或代码块,确保在同一时刻只有一个线程可以访问被锁定的资源。
3. 互斥量(Mutex):
- 在操作系统级别,可以使用互斥量确保同一时刻只有一个线程可以访问共享资源。
悲观锁的优点
-
数据一致性: 悲观锁确保了数据的一致性,因为在操作数据之前先获取了锁,避免了并发冲突。
-
简单直观: 实现相对简单,理解容易。
悲观锁的缺点
-
性能开销: 悲观锁的加锁操作会带来性能开销,尤其是在高并发的情况下,因为其他事务需要等待锁的释放。
-
死锁风险: 当多个事务相互等待对方释放锁时,可能发生死锁。
-
资源争用: 多个事务争用同一个资源时,可能导致大量的等待时间,降低系统的吞吐量。
使用悲观锁的示例:
在Java中,使用synchronized
关键字可以实现悲观锁:
public class BankAccount {private double balance;// 同步方法,使用悲观锁public synchronized void deposit(double amount) {balance += amount;}// 同步代码块,使用悲观锁public void withdraw(double amount) {synchronized (this) {if (balance >= amount) {balance -= amount;} else {System.out.println("Insufficient funds");}}}
}
synchronized
关键字确保在同一时刻只有一个线程可以执行deposit
或withdraw
方法。这就是一种悲观锁的实现方式。
相关文章:

乐观锁与悲观锁
乐观锁 乐观锁是一种并发控制的机制,其核心思想是假设多个事务之间的冲突是不太可能发生的,因此在事务处理之前不会加锁,而是在事务提交的时候再检查是否有冲突。如果发现冲突,就会回滚事务,重新尝试。 实现乐观锁的方…...

【算法】堆排序
算法-堆排序 前置知识 堆(即将更新) 思路 我们现在有一个序列,怎么对它排序? 这是一个非常经典的问题,这里我们使用一个借助数据结构的算法——堆排序解决。 这里有一个序列,要对它升序排序 4 7 3 6 5 …...

51单片机应用从零开始(三)
51单片机应用从零开始(一)-CSDN博客 51单片机应用从零开始(二)-CSDN博客 详解 KEIL C51 软件的使用建立工程-CSDN博客 详解 KEIL C51 软件的使用设置工程编绎与连接程序-CSDN博客 目录 1. 用单片机控制第一个灯亮 2. 认识单片…...

如何在 Nginx Proxy Manager(NPM)上部署静态网站
前言 众所周知,我们在之前介绍过 Nginx Proxy Manager(以下简称 NPM) 这个反向代理的神器,对于一些 Docker 搭建的 Web 项目,NPM 能够很轻松地给他们做反向代理。 然而对于一些静态网站,小伙伴们可能不知道怎么用 NP…...

http的几种方法
http的几种方法在 rfc2616 中进行了定义: https://www.rfc-editor.org/rfc/rfc2616.html#page-51 HEAD方法:HEAD方法和GET方法相同,只不过服务端只返回头,不返回消息体。GET方法:用于获取资源POST方法:用于…...

var、let、const关键字的特性,以及let、const暂时性死区的作用
var、let和const都是JavaScript中的关键字,用于声明变量。 var关键字声明的变量是函数作用域或全局作用域的,它在整个函数或全局范围内都是可用的。var没有块级作用域。 let关键字声明的变量是块级作用域的,它只在包含它的代码块中可用。le…...

IDEA 高分辨率卡顿优化
VM设置优化 -Dsun.java2d.uiScale.enabledfalse 增加该条设置,关闭高分切换 https://intellij-support.jetbrains.com/hc/en-us/articles/115001260010-Troubleshooting-IDE-scaling-DPI-issues-on-Windowsintellij-support.jetbrains.com/hc/en-us/articles/1…...

【AIGC】一起学习prompt提示词(4/4)【经典】【15种提示词技巧】
写的时候并没有设计好,要做多少期,还是有始有终的比较好,为了方便阅读,我把之前的3期,改下名字,放到这里。 【AIGC】一起学习prompt提示词(1/4) 内容摘要:提示词是什么…...

Linux实战一天一个小指令--《文件管理/文件查找》
阿丹: 作为一个java程序员进行实战开发不接触linux操作系统基本上是不可能的,所以这个专题就出现了,本文章重点解决大家关于文件管理以及文件查找查看的疑惑。我将采用语法基础用法并在下面进行高级语法的总结使用,方便大家学习和…...

CocosCreator3.8神秘面纱 CocosCreator 项目结构说明及编辑器的简单使用
我们通过Dashboard 创建一个2d项目,来演示CocosCreator 的项目结构。 等待创建完成后,会得到以下项目工程: 一、assets文件夹 assets文件夹:为资源目录,用来存储所有的本地资源,如各种图片,脚本…...

JJJ:python学习笔记
p4 没有编译的过程 源码和输入得到输出 静态语言:编译型 脚本语言:解释型 p5 又叫做胶水语言 p7 p8 p10...

SpringSecurity6从入门到上天系列第七篇:讲明白SpringBoot的自动装配完善上篇文章中的结论
文章目录 一:SpringBoot的自动装配 1:从run方法到入口类内容被注册到注解解读器中。 2:解析入口类注解到加载Bean实例 大神链接:作者有幸结识技术大神孙哥为好友,获益匪浅。现在把孙哥视频分享给大家。 孙哥链接&am…...

ClickHouse 原理解析之基础知识总结
ClickHouse 基础知识整理 参考ClickHouse 官方文档:https://clickhouse.com/docs/en/intro 一:行式存储和列式存储 1.行式存储和列式存储的区别 1.1 概念说明 行式存储:指存储结构化数据时,在底层的存储介质上,数据是以行的方式来组织的,即存储完一条记录的所有字段,再…...

最小花费——最短路
在 n 个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问 A 最少需要多少钱使得转账后 B 收到 100 元。 输入格式 第一行输入两个正整数 n,m,分别表…...

Spark DataFrame join后移除重复的列
在Spark,两个DataFrame做join操作后,会出现重复的列。例如: Dataset<Row> moviesWithRating moviesDF.join(averageRatingMoviesDF,moviesDF.col("movieId").equalTo(averageRatingMoviesDF.col("movieId")));其s…...

NextJS工程部署到阿里云linux Ecs
nextjs项目有多种部署方式,本文介绍最简单的一种方式,将源码上传到云服务器,编译后使用pm2后台运行nextjs工程。 检查node、npm是否安装 查看npm版本,如果版本较低先升级npm版本 npm -v卸载 yum remove nodejs npm -y安装新版…...

汽车以太网IOP测试新利器
IOP测试目的 汽车以太网物理层IOP(Interoperability )测试,即测试被测对象以太网物理层之间的互操作性。用于验证车载以太网PHY能否在有限时间内建立稳定的链路;此外,还用于验证车载以太网PHY可靠性相关的诊断特性&am…...

高防IP是什么?如何隐藏源站IP?如何进行防护?
高防IP是针对互联网服务器遭受大流量的DDoS攻击后导致服务不可用的情况下,推出的付费增值服务。用户在数据不转移的情况下,就可以通过配置高防IP , 将攻击流量引流到高防|P,确保源站的稳定可靠。高防IP采用的技术手段包括DDoS防护、WAF ( Web应用程序防火墙)等,它能够有效抵御来…...

ElasticSearch---查询es集群状态、分片、索引
查看es集群状态: curl -XGET http://localhost:9200/_cat/health?v如果?后面加上pretty,能让返回的json格式化。 加上?v的返回结果,如下: epoch timestamp cluster status node.total node.data shards pri rel…...

Angular 使用教程——基本语法和双向数据绑定
Angular 是一个应用设计框架与开发平台,旨在创建高效而精致的单页面应用 Angular 是一个基于 TypeScript 构建的开发平台。它包括:一个基于组件的框架,用于构建可伸缩的 Web 应用,一组完美集成的库,涵盖各种功能&…...

【ASP.NET】Hello World
文章目录 1. 几个概念2. 搭建开发环境2.1 .NET SDK2.2 IDE & Editor 3 First Project3.1 步骤3.2 模板3.3 项目结构3.4 请求的处理流程 Reference Link 1. 几个概念 .NET 是一个平台,包括 .NET Framework、.NET Core、ASP.NET、C#等,可以构建桌面、W…...

AI创作系统ChatGPT网站源码+支持最新GPT-Turbo模型+支持DALL-E3文生图/AI绘画源码
一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…...

C#_查找图片(按键精灵找图)
一、class internal class Picture{/// <summary>/// 查找图片,不能镂空/// </summary>/// <param name"subPic"></param>/// <param name"searchRect">如果为empty,则默认查找整个图像</param>…...

C#中.NET Framework4.8 控制台应用通过EF访问新建数据库
目录 一、 操作步骤 二、编写EF模型和数据库上下文 三、 移植(Migrations)数据库 四、编写应用程序并运行 前文已经说过.NET Framework4.8 控制台应用通过EF访问已经建立的数据库,这里说的已经建立的数据库指的是已经建立的SQLServer那样…...

无防御香港服务器如何防CC
虽然相对于DDos攻击,CC攻击的防护危害性相对没有那么大,但是像香港地区普遍对内地的网络比较小的话,CC攻击还是 蛮让人头痛的,实际上对CC的防护尤其是一些小体量的网站,租用高防服务器是划不来的,如果服务器…...

MyBatis的插件能在哪些地方进行拦截?
程序员的公众号:源1024,获取更多资料,无加密无套路! 最近整理了一波电子书籍资料,包含《Effective Java中文版 第2版》《深入JAVA虚拟机》,《重构改善既有代码设计》,《MySQL高性能-第3版》&…...

【BUG库】 记录自己学习工作中遇到的程序BUG
BUG库 CGoalgorithm环境相关vscode -- 保存 在这篇博客中 我会记录自己在学习和工作中遇到的一系列bug C Go algorithm 环境相关 vscode – 保存 使用vscode时未保存代码就使用终端运行 vscode和终端并不是实时同步的 需要我们自己手动使用ctrl s同步 解决方法 自己手动…...

卡尔曼家族从零解剖-(07) 高斯分布积分为1,高斯分布线性变换依旧为高斯分布,两高斯函数乘积仍为高斯。
讲解关于slam一系列文章汇总链接:史上最全slam从零开始,针对于本栏目讲解的 卡尔曼家族从零解剖 链接 :卡尔曼家族从零解剖-(00)目录最新无死角讲解:https://blog.csdn.net/weixin_43013761/article/details/133846882 文末正下方中心提供了本人 联系…...

设计模式-访问者模式(Visitor)
设计模式-访问者模式(Visitor) 一、访问者模式概述1.1 什么是访问者模式1.2 简单实现访问者模式1.3 使用访问者模式的注意事项 二、访问者模式的用途三、访问者模式实现方式3.1 递归遍历实现访问者模式3.2 迭代遍历实现访问者模式3.3 Java8 Stream API 实…...

C++二分查找算法:132 模式解法二枚举2
题目及解法一: https://blog.csdn.net/he_zhidan/article/details/134362273 分析 第一步,选择各3对应的1,如果有多个符合对应最小的1,记录num[0,j)中的最小值iMin,如果nums[j]大于iMin,则m3To1 [nums[j…...