乐观锁与悲观锁

Java 乐观锁与悲观锁 乐观锁与悲观锁的概念,之前有所讲解,这里用很小的篇幅进行知识的回顾,巩固;乐观锁与悲观锁的使用场景介绍,通过理解悲观锁与乐观锁不同的风格,理解什么场景下需要选择合适的锁,为本节的重点内容之一;了解乐观锁的缺点,乐观锁有自己的特定的缺陷,不同的锁都有自己的优点与缺点;了解乐观锁缺陷的解决方式,作为本节内容的重点之一;通过引入 Atomic 操作,实现乐观锁,为本节内容的核心,通过对比 synchronized 的实现,用两种锁机制实现同一个需求。 阅读详情

乐观锁与悲观锁

乐观锁

乐观锁就是总往好的方向想,假设管理员去修改某个用户的信息,其他管理员不可能来修改,所以每次取数据都不会上锁,只在更新的时候判断一下别人有没有去更新这个数据,常用的做法就是使用版本号机制

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

public class OptimisticLock {
	
	public static void main(String[] args) throws SQLException {
		Connection conn = null;
		PreparedStatement statementSelect = null;
		PreparedStatement statementUpdate = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			String url = "jdbc:mysql://localhost:3306/test";
			String user = "root";
			String password = "666666";
			conn = DriverManager.getConnection(url, user, password);
			// 关闭自动提交事务
			conn.setAutoCommit(false);
			String selectSQL = "select version from user_info where uuid = ?";
			statementSelect = conn.prepareStatement(selectSQL);
			statementSelect.setInt(1, 1);
			ResultSet resultSet = statementSelect.executeQuery();
			Integer version = 0;
			if(resultSet.next()) {
				version = resultSet.getInt("version");
				
			}
			System.out.println("version: "+version);
			String updateSQL = "update user_info set version = version+1, qq = ? where uuid = ? and version = ?";
			statementUpdate = conn.prepareStatement(updateSQL);
			statementUpdate.setNull(1, Types.VARCHAR);
			statementUpdate.setInt(2, 1);
			statementUpdate.setInt(3, version);
			int rows = statementUpdate.executeUpdate();
			System.out.println("更新记录数"+rows);
			conn.commit();
		} catch (Exception e) {
			conn.rollback();
			e.printStackTrace();
		} finally {
			statementSelect.close();
			statementUpdate.close();
			conn.close();
		}

	}

}

悲观锁

悲观锁就是总往坏的方向想,假设管理员去修改某个用户的信息,其他管理员也可能来修改,所以每次取数据都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。
官网连接
MySQL 使用InnoDB数据库引擎的锁机制实现悲观锁SELECT ... FOR UPDATE

For SELECT … FOR UPDATE or SELECT … LOCK IN SHARE MODE, locks are acquired for scanned rows, and expected to be released for rows that do not qualify for inclusion in the result set (for example, if they do not meet the criteria given in the WHERE clause). However, in some cases, rows might not be unlocked immediately because the relationship between a result row and its original source is lost during query execution. For example, in a UNION, scanned (and locked) rows from a table might be inserted into a temporary table before evaluation whether they qualify for the result set. In this circumstance, the relationship of the rows in the temporary table to the rows in the original table is lost and the latter rows are not unlocked until the end of query execution.

MySQL默认使用autocommit模式,使用悲观锁需将自动提交关闭,执行一个更新操作就立即将提交或回滚事务。如果是写事务,拿到锁后,一直不释放,会造成线上故障,读事务也一样。

注意:MySQL默认隔离级别是Repeatable read(可重复读),如果不提交会导致大量事务存到回滚段,导致数据库写入非常慢,容易出现故障,所以事务不管是写还是读都要尽早结束。如果出现了这样的问题,那就到mysql的cmd或者shell界面下执行命令```show engine innodb status\G```,找到ACTIVE时间长的对应的事务,找到对应的thread id,杀掉kill connection threadid,恢复业务正常运行,再去修改业务代码上的问题。

使用DeBug模式运行,在conn.commit();提交事务之前打个断点,使其长时间持有锁,然后运行其他事务处理这条记录就会处于等待释放锁中,只有该事务释放锁后其他事务才能执行事务,负责一直处与等待中。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Lock {

	public static void main(String[] args) throws SQLException {
		Connection conn = null;
		PreparedStatement statementLock = null;
		PreparedStatement statementUpdate = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			String url = "jdbc:mysql://localhost:3306/test";
			String user = "root";
			String password = "666666";
			conn = DriverManager.getConnection(url, user, password);
			// 关闭自动提交事务
			conn.setAutoCommit(false);
			String selectSQL = "SELECT * FROM user_info WHERE uuid = ? for update";
			statementLock = conn.prepareStatement(selectSQL);
			statementLock.setInt(1, 1);
			ResultSet resultSetLock = statementLock.executeQuery();
			while (resultSetLock.next()) {
				System.out.println("username: "+resultSetLock.getString("username"));
			}
			String updateSQL = "update user_info set qq = ? where uuid = ?";
			statementUpdate = conn.prepareStatement(updateSQL);
			statementUpdate.setString(1, "1234567890");
			statementUpdate.setInt(2, 1);
			int rows = statementUpdate.executeUpdate();
			System.out.println("更新记录数"+rows);
			conn.commit();
		} catch (Exception e) {
			conn.rollback();
			e.printStackTrace();
		} finally {
			statementLock.close();
			statementUpdate.close();
			conn.close();
		}

	}

}
从拧螺丝到精密装配:三菱伺服电机扭矩控制在工业自动化中的实战解析 本文深入解析三菱伺服电机扭矩控制在工业自动化中的实战应用,重点介绍MR-J4系列伺服系统的高精度扭矩响应技术。从螺丝紧固到精密装配,详细讲解扭矩控制模式的选择、硬件配置、参数设置及典型故障排查方案,帮助工程师提升生产效率和产品质量。 阅读详情

相关推荐

webapi .net core8.0配置使用Token权限认证

本人在网上找了很多版本,不是太复杂就是不行。

m0_74824592的博客 1760

使用注解方式实现 Redis 分布式锁

优雅的使用Redis分布式锁。本文使用Redisson中实现的分布式锁。

老男孩的架构路 1622

从ENVI SARscape到SNAP:手把手教你迁移哨兵1 GRD数据预处理流程(含避坑指南)

本文详细介绍了从ENVI SARscape迁移到SNAP处理哨兵1 GRD数据的全流程,包括工具哲学差异、数据准备注意事项、核心处理流程等效实现及地形校正技巧。特别针对雷达数据预处理中的常见陷阱提供避坑指南,帮助用户高效完成工具迁移并确保结果质量。

weixin_28677005的博客 485

MySQL45讲读书笔记 40讲insert语句的锁为什么这么多

一 序 本文属于极客时间MySQL45讲读书笔记系列,本文老师主要讲了特殊的insert 情况。 MySQL对自增主键锁做了优化,尽量在申请到自增id以后,就释放自增锁。还有些insert语句是属于“特殊情况”的,在执行过程中需要给其他资源加锁,或者无法在申请到自增id以后就立马释放自增锁。 二 insert … select 语句 我们先从昨天的问题说起吧。表t和t2的表结构、初始化...

bohu83的博客 759

Windows Server 2008 R2装不上VMware Tools?别急,手动安装驱动补丁的保姆级教程来了

本文提供了Windows Server 2008 R2手动安装VMware Tools驱动补丁的详细教程,解决驱动签名验证失败问题。通过获取特定补丁文件、创建安装介质、挂载虚拟机并安装补丁等步骤,帮助用户顺利完成VMware Tools安装,提升虚拟机功能与性能。

weixin_28335283的博客 467

别再死记硬背公式了!用ADS手把手教你仿真一个4GHz镜像抑制混频器(附完整工程文件)

本文详细介绍了使用Keysight ADS软件设计和仿真4GHz镜像抑制混频器的完整流程。从理论分析到实际工程实现,涵盖分支线耦合器设计、二极管建模、噪声系数仿真及性能优化等关键步骤,帮助工程师摆脱公式死记硬背,掌握实用的射频电路设计技能。附完整工程文件,可直接应用于实际项目开发。

weixin_28683391的博客 494

面试必备之乐观锁与悲观锁

悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放。也就是说,共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程。像 Java 中和等独占锁就是悲观锁思想的实现。悲观锁通常多用于写多比较多的情况下(多写场景),避免频繁失败和重试影响性能。

JavaGuide 30万+

【1.2】Costas环的基本原理概述

Costas环是一种用于载波恢复的相干解调技术,可直接从BPSK等抑制载波信号中恢复本地载波并完成解调。其核心结构包含同相/正交双支路处理,通过混频、低通滤波后,利用I/Q支路信号乘积进行相位误差检测,经环路滤波器调节VCO输出频率,实现载波同步。课程将重点讲解Costas环的MATLAB仿真实现、系统性能分析及FPGA开发,包括信号产生、频偏模拟、滤波器设计等模块,并通过AWGN信道和不同频偏条件下的测试验证系统性能。该技术无需单独提取载波,在数字通信系统中具有重要应用价值。

fpga/matlab/simulink算法仿真工程 450

Java悲观锁与乐观锁

Java悲观锁与乐观锁锁的目的实例悲观锁实现乐观锁实现总结 锁的目的 多线程编程如有共用资源的使用时,需要保证数据安全,资源需要同步处理。处理资源的手段可以有:互斥同步与非阻塞同步。实现分别对应:悲观锁与乐观锁。 实例 开20个线程进行计数,每个线程计算到10000。分别使用悲观锁与乐观锁来实现。 悲观锁实现 悲观锁是主要使用synchronized实现,通过锁住对应的对象,独占资源的方式。 de...

Richy的博客 5045

UNet 改进(22):结合Transformer结构

保留了UNet的经典编码器-解码器结构在瓶颈层使用Transformer替代传统的卷积层采用跳跃连接保持空间细节信息使用双卷积块(DoubleConv)作为基础构建模块。

2401_82355416的博客 773

扩散模型与强化学习(13):In-Context Reward Hacking现象与解决方案

奖励作弊(Reward Hacking)指智能体通过钻规则漏洞而非真正完成任务来最大化奖励信号。以论文编辑实验为例,研究提出“上下文奖励作弊”(ICRH)概念,即模型利用共享上下文钻空子,如盲目添加“正确!”或输出无关内容。实验发现,模型规模扩大可能加剧ICRH,且提示词优化难以根治。与传统奖励作弊不同,ICRH发生在部署阶段,由通用性驱动。应对建议包括多轮测试、多样化反馈及异常场景模拟,但尚无完美解决方案。

沉迷单车的追风少年 1317

什么是乐观锁与悲观锁、乐观锁的缺点

数据库中的乐观锁和悲观锁用来解决什么问题? 用来解决不可重复读和幻读的。

本人的技术和文笔有限,正在努力成长中,请各位朋友多多指正与包涵! 847

在MATLAB和Simulink中设计并仿真一个电动汽车BMS热管理系统

电动汽车电池管理系统(Battery Management System, BMS)中的热管理是确保电池安全运行、延长寿命和提高性能的关键环节。通过Simulink进行BMS热管理仿真是验证控制策略的有效性、优化散热设计并降低开发成本的重要手段。以下是如何在MATLAB和Simulink中设计并仿真一个电动汽车BMS热管理系统的详细步骤。通过上述步骤,我们成功设计并实现了基于Simulink的电动汽车BMS热管理系统仿真。

xiaoheshang_123的博客 702

并发:乐观锁与悲观锁

何谓悲观锁与乐观锁 悲观锁 乐观锁 两种锁的使用场景 乐观锁常见的两种实现方式 1. 版本号机制 2. CAS算法 乐观锁的缺点 1 ABA 问题 2 循环时间长开销大 3 只能保证一个共享变量的原子操作 CAS与synchronized的使用情景 何谓悲观锁与乐观锁 乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向...

Java Punk 1325

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

【MySQL】中的乐观锁与悲观锁

为什么需要锁 在并发环境下,如果多个客户端访问同一条数据,此时就会产生数据不一致的问题,如何解决,通过加锁的机制,常见的有两种锁,乐观锁和悲观锁,可以在一定程度上解决并发访问。 乐观锁 乐观锁,顾名思义,对加锁持有一种乐观的态度,即先进行业务操作,不到最后一步不进行加锁,"乐观"的认为加锁一定会成功的,在最后一步更新数据的时候在进行加锁,乐观锁的实现方式一般为每一条数据加一个版本号,具体流程...

chenchongg的博客 2304

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

悲观锁与乐观锁

悲观锁与乐观锁是并发控制的两种策略。悲观锁(如synchronized、数据库行锁)假设数据冲突频繁,通过加锁确保独占性,适合高冲突场景但性能开销大。乐观锁(如CAS、版本号机制)假设冲突少,通过版本检测或原子操作实现,适用于低冲突环境,性能更好但需处理ABA问题。关键区别在于:悲观锁"先上锁后操作",可能导致死锁;乐观锁"先操作后检测",需解决重试问题。数据库和Java并发包中均有对应实现,选择取决于具体场景的冲突频率和性能要求。

诗酒趁年华 1152

一文彻底理解乐观锁与悲观锁

通过阅读本文可以获得什么 1、什么是乐观锁? 2、乐观锁实现方式都有什么? 3、乐观锁优缺点有哪些? 4、乐观锁适用场景? 5、什么是悲观锁? 6、悲观锁实现方式有哪几种? 7、悲观锁优缺点? 8、悲观锁的适用场景? 首先,我们先看一下什么是乐观锁,在我个人理解,乐观锁可以抽象为去银行取钱,假如银行没有人排队,所以不需要取号,直接去柜台A就可以办理业务。反之悲观锁就是假如去银行取钱,每次去都好巧不巧的都有人在柜台A排队,所以此时需要取号,然后等叫号在去柜台A办理业务。(假设银行只有一个柜台A,不..

醉鱼的博客 3027

面试题总结——乐观锁与悲观锁

面试题总结——乐观锁与悲观锁  一、乐观锁与悲观锁对比   1.悲观锁    共享资源每次只给一个线程使用,其他线程阻塞,需等到当前线程使用完后才能使用(总是假设最坏的情况,每次拿到数据后都会认为别人会修改该数据,因此每次拿数据时都会上锁,阻塞其他人)    MySQL中的锁机制:行锁,表锁,读锁,写锁;Java中的synchronized和ReentrantLock独占锁。   2.乐观锁   ...

xiaoaxiao 1549

乐观锁与悲观锁的对比

乐观锁与悲观锁的区别 1.乐观锁与悲观锁是什么 乐观锁:乐观锁表示当线程对数据进行操作时,认为不会有其他线程来修改数据,所以先不上锁,对数据操作之后,检查此时的数据是否和最开始线程进入时的数据一致,如果一致,那么就可以认为没有其他线程对数据进行修改,现在可以对数据进行更新;如果不一致,那么就再读数据,再操作再检查数据,直到可以更新数据为止。 悲观锁:表示当前线程对数据操作时,认为一定会有其他线程去...

weixin_44916741的博客 610

Mysql乐观锁与悲观锁的区别

05 mysql-乐观锁与悲观锁的区别 文章目录1、悲观锁2、乐观锁3、两种锁的使用场景4、乐观锁常见的两种实现方式4.1、 版本号机制4.2、 CAS算法5、乐观锁的缺点5.1、 ABA 问题5.2、 循环时间长开销大5.3、 只能保证一个共享变量的原子操作 1、悲观锁 ​ 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数...

时光、疏离了记忆づ童话的博客 2679

乐观锁,悲观锁与Golang

悲观锁 悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。 乐观锁 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适

月守护的博客 1954

Redis 悲观锁与乐观锁

答:避免误删锁问题。如果直接用 DEL 命令,可能出现:客户端 A 获取锁后超时,锁自动释放,客户端 B 获取锁,此时客户端 A 执行 DEL 会删除客户端 B 的锁。思想:悲观地认为每次操作数据都会发生并发冲突,因此在操作数据前,必须先获取锁,确保同一时间只有一个客户端能操作该数据,其他客户端需等待锁释放后才能执行。为了解决分布式场景下的并发冲突,Redis衍生出了悲观锁和乐观锁两种核心锁机制,二者的设计思路完全相反,适用于不同的并发场景。如果版本号不一致,说明数据已被修改,放弃当前更新或重试。

2402_83493359的博客 1278

乐观锁与悲观锁的概念

在多线程或多进程并发访问同一资源的情况下,为了防止数据的不一致性和竞态条件,常常需要使用锁机制来控制并发访问。锁机制大致可以分为 乐观锁(Optimistic Locking)和 悲观锁(Pessimistic Locking)。这两种锁的工作方式不同,各有优缺点,适用于不同的场景

nbsaas-boot基于Request-Response的企业级快速开发框架 1427
上一篇: 数据库连接池原理
下一篇: 门户模式
l_learning
博客等级 码龄8年 15粉丝 82原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值