乐观锁和悲观锁

乐观锁和悲观锁

1基本区别

名称

核心点

说明

场景

悲观锁(pessimistic lock)

操作之前加锁

(最坏情况)

每次拿数据时都认为别人会修改,因此每次拿数据时都上锁

注意点:

Mysql innodb中使用悲观锁一定要关闭自动提交属性(默认autocommit模式,即执行一个更新操作后,mysql会立刻将结果提交。)需要设置autocommit=0

写多高并发

关系型数据库行锁,表锁,读写锁等。

JavasynchronizedReentrantLock等独占锁

乐观锁(opitmistic lock)

操作之前不加锁

(最好情况)

每次拿数据时认为别人不会修改,因此不上锁,更新时判断下数据有没有被更新

读多低并发。

版本号和cas方式实现。

数据库提供的类似于write_condition机制。

java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的

2乐观锁实现方式

1)版本号

update table set x=x+1, version=version+1 where id=#{id} and version=#{version};

2)cas方式

Compare and swap(比较与交换),无锁情况下实现多线程间变量同步。即非阻塞同步(non-blocking synchronization)

实现操作数:

需要读写的内存值V,进行比较的值A,拟写入的新值B

当且仅当V值等于A时,CAS通过原子方式用新值B更新V的值,否则不会执行任何操作(比较和替换是一个原子操作),一般情况下是一个自旋操作(即不断重试)

https://blog.csdn.net/hongchangfirst/article/details/26004335

https://blog.csdn.net/liaohaojian/article/details/62416972

https://blog.csdn.net/L_BestCoder/article/details/79298417

https://blog.csdn.net/qq_34337272/article/details/81072874

2.1乐观锁缺点

问题

说明

解决方法

ABA问题

如果一个变量V初次读取时是A值,且在准备赋值时检查到仍然是A值,不能确定没有被其他线程修改过。因为可能被修改为其他值,然后又改回A值。即cas操作会误认为从来没有被修改过,即ABA问题。

Jdk1.5后的AtomicStampedReference 类提供了compareAndSet。即先检查当前引用是否等于预期引用,并当前标志是否等于预期标志,如果全等,则以原子方式将该引用和标志值设置为给定的更新值。

循环时间长开销大

自旋CAS即不成功就一直循环执行直到成功,如果长时间不成功会增加cpu开销。

 

 

2.2补充说明

CASsynchronized使用场景:

 

说明

其他

CAS

低并发情况下,使用synchronized同步锁进行线程阻塞和唤醒切换额外浪费cpu资源。而cas基于硬件实现,不需要进入内核,切换线程,操作自旋几率少,性能更高

注意:cas实现方式是使用cpu层面的命令保证原子性,硬件级别的!

synchronized

高并发情况下,线程冲突严重,cas自旋几率大,浪费过多cpu资源,效率低于synchronized

Jdk1.6后对synchronized进行了优化

https://blog.csdn.net/qq_34337272/article/details/81072874

3悲观锁

共享锁和排它锁是悲观锁的不同实现,一般数据库已实现,可直接调用。

3.1Mysql中共享锁,排他锁,悲观锁,乐观锁

3.1.1  innodbmyisam

引擎

说明

其他

innodb

myisam最大不同点

1)innodb支持事务

2)Innodb采用行锁

注意:行锁不是直接锁记录,而是锁索引。

如果sql操作了主键索引则锁主键索引,操作非主键索引则先锁该非主键索引,再锁主键索引。如果没有索引或不通过索引条件检索数据,那么innodb将锁表。

Mysql5.5之后使用innodb

myisam

Myisam操作数据使用表锁,性能低

Mysql5.5之前默认使用myisam存储引擎

3.1.2  mysql中锁

注意:数据库增删改操作默认都会加排他锁,而查询不会加任何锁。

数据库规定:同一资源上不能同时加共享锁和排他锁。

类别

说明

场景

共享锁

对某一资源加共享锁,自身和其他人都可以读该资源,但无法修改。必须等所有共享锁释放完才能修改

(读锁)

多个不同事务对同一个资源共享同一个锁。(相当于一个门有多个钥匙)

select * from myemployeee where id=322051 lock in share mode

排他锁

对某一资源加排他锁,自身可进行增删改查,其他人无法进行任何操作

(写锁)

select * from myemployeee where id=322051 for update

https://blog.csdn.net/puhaiyang/article/details/72284702

https://blog.csdn.net/localhost01/article/details/78720727

mysql中的锁描述的还是不太清楚,后续再进行理解。

原文地址:https://www.cnblogs.com/cslj2013/p/10925850.html