什么是乐观锁、悲观锁、共享锁、排他锁?
2019-06-30 本文已影响35人
刘一一同学
1. 悲观锁(Pessimistic Lock)
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其他线程阻塞,用完后再把资源转让给其它线程)。悲观锁适用于多写的场景。
2. 乐观锁(Optimistic Lock)
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以每次拿数据的时候都不会上锁,但是在个更新数据的时候就会判断一下在此期间别人又没有去更新这个数据,可以使用版本号机制和 CAS 算法实现。乐观锁适用于多读的场景,可以提高吞吐量,像数据库提供的类似于write_condition
机制,其实都是提供的乐观锁。在 Java 中 java.util.concurrent.atomic
包下面的原子变量类就是使用了乐观锁的一种实现方式 CAS 实现的。
3. 共享锁(读锁,简称S锁)
多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
4. 排他锁(写锁,简称X锁)
如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务可以对数据行进行读取和修改。
注意:MySQL 的 InnoDB 引擎,update、delete、insert 都会自动给涉及到的数据加上排他锁,selete 语句默认不会加任何类型的锁,如果需要加排他锁可以使用
select ....for update
语句,加共享锁可以使用select...lock in share mode
语句。所以如果加过排他锁的数据行,其他事务是不能修改的,也不能通过for update
和lock in shar mode
锁的方式查询数据,但可以通过select...from...
查询数据,因为普通查询没有任何锁机制。
- Java 乐观锁通过 CAS 实现,悲观锁通过 synchronize 实现。
- MySQL 乐观锁通过 MVCC,也就是版本实现,悲观锁可以通过
select... for update
加上排它锁。