数据库的乐观锁、悲观锁的理解

乐观锁的理解:

  • 乐观锁顾名思义就是很乐观,别人在拿数据的时候认为别人不会修改数据,所以不会上锁,但是在更新数据时会判断在此期间别人有没有修改这个数据,因为使用版本号机制来实现乐观锁。

实现乐观锁的方法:

  • - 版本号机制: 在数据表中加一个版本号字段version,表示被修改的次数,当数据被修改时,version的值会加1。 在读取数据时也会读取version的值,在提交更新时,若刚才读取到的值和数据库中的version的值相等则更新数据,否则重试更新操作,直到更新成功。

  • CAS算法:(比较与交换) 这种算法的实现方式为:在读取到数据库中的数据时,先对数据进行保存,当处理完逻辑时,则再执行更新语句,更新语句如下:update xxx
    set name =“新的名字” where name=“原来的名字”。
    当多线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程不会被挂起,二十被告知这次竞争中失败,并可以再尝试。

    但是CAS也会导致ABA的问题:ABA问题如下,变量Q初次读取到的数据为A值,当在准备赋值时检查到它仍然时A值,但是这段时间内可以Q的值已经被更改为其它值,但是又改回了A值。但是这样的操作在CAS看来这是没有更改过的。

Java对CAS的支持
JDK 5之前都是靠synchronized关键字保证同步的,这是一种独占锁,也就是悲观锁

悲观锁的理解:

  • 悲观锁是一种假设最坏的情况,即每次拿数据的时候都会认为别人也会修改数据,所以在每次拿数据时会上锁,这样别人拿这个数据时就会阻塞知道它拿到锁。传统的关系型数据库很多这种锁机制,比如,行锁、表锁、读锁、都是在做操作之前上锁,Java中的synchronized和ReentrantLock等独占锁就是悲观锁的思想。

实现悲观锁的方法:

  • 通过数据库锁机制实现,即对查询语句添加for update关键字。
    如update xxx set a=1 where id=1 for
    update,此时请求A开启了事务并执行该更新语句同时未提交事务时,另一个线程B发起请求了,此时B会阻塞在加了锁的查询语句上,知道A提交了事务或者回滚了事务,保证了访问的隔离性。

乐观锁多用于读的操作

悲观锁多用于写的操作

发布了55 篇原创文章 · 获赞 6 · 访问量 4009

猜你喜欢

转载自blog.csdn.net/qq_40126996/article/details/100727602
今日推荐