悲观锁与乐观锁的一些使用

  1 首先我们来了解一下 乐观锁与悲观锁的区别
  2
  3 乐观锁的思路一般是表中增加版本字段,更新时where语句中增加版本的判断,算是一种CAS(Compare And Swep)操作,
  4 商品库存场景中number起到了版本控制(相当于version)的作用( AND number=#{number})。
  5
  6 悲观锁之所以是悲观,在于他认为本次操作会发生并发冲突,所以一开始就对商品加上锁(SELECT … FOR UPDATE),
  7 然后就可以安心的做判断和更新,因为这时候不会有别人更新这条商品库存。
  8
  9 从中我们也可以知道只要更新数据是依赖读取的数据作为基础条件的,就会有并发更新问题,需要乐观锁或者悲观锁取解决,
 10 特别实在计数表现明显。又比如在更新数据不依赖查询的数据的就不会有问题,
 11 例如修改用户的名称,多人同时修改,结果并不依赖于之前的用户名字,这就不会有并发更新问题。
 12
 13
 14 ================================
 15 1. 悲观锁
 16
 17 顾名思义就是很悲观,每次拿数据都会认为别的线程会修改该数据,所以会给数据上锁;
 18
 19 这样抢到锁的线程运行,取到数据做操作,
 20
 21 这期间其他线程想要访问该数据时,都是阻塞block挂起状态,操作不了;
 22
 23 核心就是不支持多并发,是单线程操作,通过抢占时间片的方式来抢锁的使用权,把并发变成了串行。
 24
 25 共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程。
 26 应用场景:
 27
 28 悲观锁适用于多写的场景,保证线程安全和数据安全
 29
 30 mysql的行锁、表锁、读锁、写锁;
 31
 32 java中的synchronized。
 33
 34 =================================
 35 2. 乐观锁
 36
 37 顾名思义就是很乐观,每次拿数据都认为别的线程不会修改数据,因此不会给数据上锁;
 38
 39 但会在数据更新时判断一下,在此期间其他线程有没有对该数据做更新,最终通过多个线程的逐一更新获取数据的最终值;
 40 应用场景:
 41
 42 乐观锁适用于多读的场景,获取数据不再创建、销毁锁,减少了锁的开销,加大了数据的吞吐量,
 43
 44 Redis等非关系型数据库
 45
 46 ps:Redis是单线程操作,把事务封闭在单一线程中,避免了线程的安全问题,所以里面没有加悲观锁;
 47
 48        不过对于依赖多个Redis操作的复合操作来说,还是需要加锁的,而且有可能是分布式锁,也可以用LUA脚本,用任务队列的方式解决多任务并发的问题。
 49
 50
 51
 52
 53 ========================SQlserver上的悲观锁解决方案==============================
 54 https://blog.csdn.net/gudenren/article/details/4397291
 55
 56 ===》》》悲观锁定解决方案
 57
 58 declare @CardNo varchar(20)
 59 Begin Tran
 60
 61 -- 选择一张未使用的卡
 62 select top 1 @CardNo=F_CardNo
 63 from Card with (UPDLOCK) where F_Flag=0 //---F_Flag=0表示没有被人注册使用这张卡
 64
 65 -- 延迟50秒,模拟并发访问.
 66 waitfor delay ‘000:00:50‘
 67
 68 -- 把刚才选择出来的卡进行注册.
 69
 70 update Card
 71 set F_Name=user,
 72 F_Time=getdate(),
 73 F_Flag=1
 74 where F_CardNo=@CardNo
 75
 76 commit
 77
 78 注重其中的区别了吗?with(updlock),是的,我们在查询的时候使用了with (UPDLOCK)选项,在查询记录的时候
 79 我们就对记录加上了更新锁,表示我们即将对次记录进行更新.注重更新锁和共享锁是不冲突的,也就是其他用户还可以
 80 查询此表的内容,但是和更新锁和排它锁是冲突的.所以其他的更新用户就会阻塞.假如我们在另外一个窗口执行此代码,
 81 同样不加waifor delay子句.两边执行完毕后,我们发现成功的注册了两张卡.
 82 可能我们已经发现了悲观锁定的缺点:当一个用户进行更新的事务的时候,其他更新用户必须排队等待,即使那个用户更新的不是同一条记录.
 83
 84
 85
 86
 87 ======》》》乐观锁
 88 乐观锁定解决方案
 89
 90 -- 首先我们在Card表里边加上一列F_TimeStamp 列,该列是varbinary(8)类型.但是在更新的时候这个值会自动增长.
 91
 92 alter table Card add F_TimeStamp timestamp not null
 93
 94 -- 悲观锁定
 95 declare @CardNo varchar(20)
 96 declare @timestamp varbinary(8)
 97 declare @rowcount int
 98
 99 Begin Tran
100
101 -- 取得卡号和原始的时间戳值
102 select top 1 @CardNo=F_CardNo,
103 @timestamp=F_TimeStamp
104 from Card
105 where F_Flag=0
106
107 -- 延迟50秒,模拟并发访问.
108 waitfor delay ‘000:00:50‘
109
110 -- 注册卡,但是要比较时间戳是否发生了变化.假如没有发生变化.更新成功.假如发生变化,更新失败.
111
112 update Card
113 set F_Name=user,
114 F_Time=getdate(),
115 F_Flag=1
116 where [email protected] and F_TimeStamp=@timestamp
117 set @rowcount=@@rowcount
118 if @rowcount=1
119 begin
120 print ‘更新成功!‘
121 commit
122 end
123 else if @rowcount=0
124 begin
125 if exists(select 1 from Card where F_CardNo=@CardNo)
126 begin
127 print ‘此卡已经被另外一个用户注册!‘
128 rollback tran
129 end
130 else
131 begin
132 print ‘并不存在此卡!‘
133 rollback tran
134 end
135 end
136
137 在另外一个窗口里边执行没有waitfor的代码,注册成功后,返回原来的窗口,我们就会发现到时间后它显示的提示是此卡以
138 被另外一个用户注册的提示.很明显,这样我们也可以避免两个用户同时注册一张卡的现象的出现.同时,
139 使用这种方法的另外一个好处是没有使用更新锁,这样增加的系统的并发处理能力.
140
141 总结:上边我具体介绍了乐观锁定和悲观锁定的使用方法,在实际生产环境里边,假如并发量不大,
142 我们完全可以使用悲观锁定的方法,因为这种方法使用起来非常方便和简单.但是假如系统的并发非常大的话,
143 悲观锁定会带来非常大的性能问题,所以我们就要选择乐观锁定的方法.

原文地址:https://www.cnblogs.com/Fengge518/p/11725655.html

时间: 2024-11-09 03:59:59

悲观锁与乐观锁的一些使用的相关文章

Oracle数据库悲观锁与乐观锁详解

数据的锁定分为两种方法,第一种叫做悲观锁,第二种叫做乐观锁.什么叫悲观锁呢,悲观锁顾名思义,就是对数据的冲突采取一种悲观的态度,也就是说假设数据肯定会冲突,所以在数据开始读取的时候就把数据锁定住.而乐观锁就是认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让用户返回错误的信息,让用户决定如何去做. 先从悲观锁开始说.在SqlServer等其余很多数据库中,数据的锁定通常采用页级锁的方式,也就是说对一张表内的数据是一种串行化的更新插

数据库中的悲观锁和乐观锁详解

数据中的锁分为两类:悲观锁和乐观锁,锁还有表级锁.行级锁 表级锁例如: SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除 SELECT * FROM table WITH (TABLOCKX) 其他事务不能读取表,更新和删除 行级锁例如: select * from table_name where id = 1 for update; 悲观锁(Pressimistic Locking) 对数据被外界(包括本系统当前的其他事务,以及来自

025 hibernate悲观锁、乐观锁

Hibernate谈到悲观锁.乐观锁,就要谈到数据库的并发问题,数据库的隔离级别越高它的并发性就越差 并发性:当前系统进行了序列化后,当前读取数据后,别人查询不了,看不了.称为并发性不好 数据库隔离级别:见前面章级 025-1悲观锁: 悲观锁:具有排他性(我锁住当前数据后,别人看到不此数据) 悲观锁一般由数据机制来做到的. 悲观锁的实现 通常依赖于数据库机制,在整修过程中将数据锁定,其它任何用户都不能读取或修改(如:必需我修改完之后,别人才可以修改) 悲观锁的适用场景: 悲观锁一般适合短事务比较

悲观锁及乐观锁

1.Volatile:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 2.悲观锁与乐观锁:http://www.cnblogs.com/softidea/p/5309312.html 3.乐观锁的一种实现方式:http://www.tuicool.com/articles/yiyy6bI

mysql-mysql悲观锁和乐观锁

1.mysql的四种事务隔离级别 I. 对于同时运行多个事务,当这些事务访问数据库中的相同数据时,如果没有采取必要的隔离机制,就会导致各种并发问题. (1)脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的. (2)不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了. (3)幻读: 对于两个事物 T1, T2,

数据库事务的悲观锁和乐观锁

转载出处:http://www.hollischuang.com/archives/934 在数据库的锁机制中介绍过,数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性. 乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段. 无论是悲观锁还是乐观锁,都是人们定义出来的概念,可以认为是一种思想.其实不仅仅是关系型数据库系统中有乐观锁和悲观锁的概念,像memcache.hibernate.tair

Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS

首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁.传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁.再比如Java里面的同步原语synchronized关键字的实现也是悲观锁. 乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版

Hibernate 再接触 悲观锁和乐观锁

为什么取1248 二进制 CRUD 移位效率高 在并发和效率选择一个平衡点 一般不会考虑幻读 因为我们不会再一个事务里查询两次,(只能设置为seralizable) 悲观锁和乐观锁的前提是read-uncommitted 在数据库中 默认是repeatable read 悲观锁是想着总有人要更改 所以使用数据库的锁 乐观锁是在程序级别的 设置一个版本号 如果前后不一致就进行自己的操作 例子 悲观所 Acocount package com.bjsxt.hibernate; import java

zbb20180929 thread 自旋锁、阻塞锁、可重入锁、悲观锁、乐观锁、读写锁、对象锁和类锁

1.自旋锁自旋锁可以使线程在没有取得锁的时候,不被挂起,而转去执行一个空循环,(即所谓的自旋,就是自己执行空循环),若在若干个空循环后,线程如果可以获得锁,则继续执行.若线程依然不能获得锁,才会被挂起.使用自旋锁后,线程被挂起的几率相对减少,线程执行的连贯性相对加强.因此,对于那些锁竞争不是很激烈,锁占用时间很短的并发线程,具有一定的积极意义,但对于锁竞争激烈,单线程锁占用很长时间的并发程序,自旋锁在自旋等待后,往往毅然无法获得对应的锁,不仅仅白白浪费了CPU时间,最终还是免不了被挂起的操作 ,

聊聊数据库乐观锁和悲观锁,乐观锁失败后重试

在写入数据库的时候需要有锁,比如同时写入数据库的时候会出现丢数据,那么就需要锁机制. 数据锁分为乐观锁和悲观锁,那么它们使用的场景如下: 1. 乐观锁适用于写少读多的情景,因为这种乐观锁相当于JAVA的CAS,所以多条数据同时过来的时候,不用等待,可以立即进行返回. 2. 悲观锁适用于写多读少的情景,这种情况也相当于JAVA的synchronized,reentrantLock等,大量数据过来的时候,只有一条数据可以被写入,其他的数据需要等待.执行完成后下一条数据可以继续. 他们实现的方式上有所