当前位置:   article > 正文

悲观锁与乐观锁

悲观锁与乐观锁

一、悲观锁

(1)mysql悲观锁

下面表需要加索引为行锁,不加索引为表锁

①.查询和修改必须在一个事务中

  1. /**
  2. * 更新Inter数据
  3. */
  4. @Override
  5. @Transactional
  6. public void updateInterData() {
  7. InterBean interBean = interMapper.queryInterData("interface1");
  8. Long interUrl = interBean.getInterUrl();
  9. interUrl+=1;
  10. interBean.setInterUrl(interUrl);
  11. interMapper.updateInterData(interBean);
  12. }

②. 查询语句末尾需要加for update

  1. <select id="queryInterData" resultMap="baseResult">
  2. select id,inter_number,inter_url from interface.lock_test_table where inter_number =#{interNumber} for update
  3. </select>

(2)代码块实现

1、synchronized

synchronized修饰普通方法,锁对象默认为this

  1. public class SynchronizedObjectLock implements Runnable {
  2. static SynchronizedObjectLock instence = new SynchronizedObjectLock();
  3. @Override
  4. public void run() {
  5. // 同步代码块形式——锁为this,两个线程使用的锁是一样的,线程1必须要等到线程0释放了该锁后,才能执行
  6. synchronized (this) {
  7. System.out.println("我是线程" + Thread.currentThread().getName());
  8. try {
  9. Thread.sleep(3000);
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. System.out.println(Thread.currentThread().getName() + "结束");
  14. }
  15. }
  16. public static void main(String[] args) {
  17. Thread t1 = new Thread(instence);
  18. Thread t2 = new Thread(instence);
  19. t1.start();
  20. t2.start();
  21. }
  22. }

2、lock锁

  • lock(): 加锁
  • unlock(): 解锁
  • tryLock(): 尝试获取锁,返回一个boolean值
  • tryLock(long,TimeUtil): 尝试获取锁,可以设置超时

Lock一般使用的例子,注意ReentrantLock是Lock接口的实现。

  1. package com.hjt.lock;
  2. import java.util.concurrent.locks.Lock;
  3. import java.util.concurrent.locks.ReentrantLock;
  4. public class LockTest {
  5. private Lock lock = new ReentrantLock();
  6. //需要参与同步的方法
  7. private void method(Thread thread){
  8. try {
  9. lock.lock();
  10. System.out.println("线程名"+thread.getName() + "获得了锁");
  11. }catch(Exception e){
  12. e.printStackTrace();
  13. } finally {
  14. lock.unlock();
  15. System.out.println("线程名"+thread.getName() + "释放了锁");
  16. }
  17. }
  18. public static void main(String[] args) {
  19. LockTest lockTest = new LockTest();
  20. //线程1
  21. Thread t1 = new Thread(new Runnable() {
  22. @Override
  23. public void run() {
  24. lockTest.method(Thread.currentThread());
  25. }
  26. }, "t1");
  27. Thread t2 = new Thread(new Runnable() {
  28. @Override
  29. public void run() {
  30. lockTest.method(Thread.currentThread());
  31. }
  32. }, "t2");
  33. t1.start();
  34. t2.start();
  35. }
  36. }
  37. //执行情况:线程名t1获得了锁
  38. // 线程名t1释放了锁
  39. // 线程名t2获得了锁
  40. // 线程名t2释放了锁

二、乐观锁

(1)CAS机制

CAS操作包括了3个操作数:

  1. 1) 需要读写的内存位置(V)
  2. 2) 进行比较的预期值(A)
  3. 3) 拟写入的新值(B)

(2)版本号机制

1、MyBatis-Plus乐观锁

数据库中添加version字段
取出记录时,获取当前version

SELECT id,`name`,price,`version` FROM product WHERE id=1

更新时,version + 1,如果where语句中的version版本不对,则更新失败

UPDATE product SET price=price+50, `version`=`version` + 1 WHERE id=1 AND`version`=1

修改实体类

  1. @Data
  2. public class Product {
  3. private Long id;
  4. private String name;
  5. private Integer price;
  6. @Version //标识乐观锁版本号字段
  7. private Integer version;
  8. }

添加乐观锁插件配置

  1. @Configuration
  2. //扫面指定的mapper包
  3. @MapperScan("com.xin.mybatisplus2.mapper")
  4. public class MyBatisPlusConfig {
  5. @Bean
  6. public MybatisPlusInterceptor mybatisPlusInterceptor() {
  7. MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();
  8. //new PaginationInnerInterceptor(DbType.MYSQL):创建分页插件,数据库类型是MySQL
  9. interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  10. //添加乐观锁插件
  11. interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
  12. return interceptor;
  13. }
  14. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/435857
推荐阅读
相关标签
  

闽ICP备14008679号