乐观锁

【Spring】27、JPA 实现乐观锁@Version注解的使用

血红的双手。 提交于 2020-01-13 01:17:23
持久层使用jpa时,默认提供了一个注解@Version来实现乐观锁 简单来说就是用一个version字段来充当乐观锁的作用。 先来设计实体类 /** * Created by xujingfeng on 2017/1/30. */ @Entity @Table(name = "t_student") public class Student { @Id @GenericGenerator(name = "PKUUID", strategy = "uuid2") @GeneratedValue(generator = "PKUUID") @Column(length = 36) private String id; @Version private int version; private String name; //getter()... //setter()... } Dao层 /** * Created by xujingfeng on 2017/1/30. */ public interface StudentDao extends JpaRepository<Student,String>{ @Query("update Student set name=?1 where id=?2") @Modifying @Transactional int

mysql:悲观锁与乐观锁

好久不见. 提交于 2020-01-12 09:07:59
为什么会使用到数据库级别的锁? 你可能会有这么一个疑问:现在的程序已经提供了很完善的锁机制来保证多线程的安全问题,还需要用到数据库级别的锁吗?我觉得还是需要的,为什么呢?理由很简单,我们再编程中使用的大部分锁都是单机,尤其是现在分布式集群的流行,这种单机的锁机制就保证不了线程安全了,这个时候,你可能又会想到使用redis的setNX分布式锁 或者 zookeeper的强一致性来保证线程安全,但是这里我们需要考虑到一个问题,那就是成本问题,有的时候使用redis分布式锁以及zookeeper会增加维护的成本,结合实际出发,再说没有百分百安全的程序,所以再数据库层加锁,也能将安全再提升一级,所以还是有必要的。 什么是悲观锁 悲观锁,正如其名,具有强烈的独占和排他特性。它指的是对数据被外界(包括本系统当前的其他 事务 ,以及来自外部系统的 事务处理 )修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的 排他性 ,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。 通俗的讲:开启一个事务之后开启悲观锁,这时候数据库将会锁着你需要查询的某条数据或者某张表,其他事务中的查询将会处于阻塞状态,开启悲观锁事务里面操作不会被阻塞,这点有点类似java中的互斥锁,那什么时候锁记录

[转帖]Java:CAS(乐观锁)

你离开我真会死。 提交于 2020-01-10 04:35:56
Java:CAS(乐观锁) https://www.jianshu.com/p/ae25eb3cfb5d 本文讲解CAS机制,主要是因为最近准备面试题,发现这个问题在面试中出现的频率非常的高,因此把自己学习过程中的一些理解记录下来,希望能对大家也有帮助。 什么是悲观锁、乐观锁?在java语言里,总有一些名词看语义跟本不明白是啥玩意儿,也就总有部分面试官拿着这样的词来忽悠面试者,以此来找优越感,其实理解清楚了,这些词也就唬不住人了。 synchronized是悲观锁,这种线程一旦得到锁,其他需要锁的线程就挂起的情况就是悲观锁。 CAS操作的就是乐观锁,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。 在进入正题之前,我们先理解下下面的代码: private static int count = 0; public static void main(String[] args) { for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } //每个线程让count自增100次 for (int i

【MySQL】悲观锁&乐观锁

送分小仙女□ 提交于 2020-01-07 15:59:39
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个非常基础的概念。本文将对这两种常见的锁机制在数据库数据上的实现进行比较系统的介绍。 悲观锁(Pessimistic Lock) 悲观锁的特点是先获取锁,再进行业务操作,即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。通常所说的“一锁二查三更新”即指的是使用悲观锁。通常来讲在数据库上的悲观锁需要数据库本身提供支持,即通过常用的select … for update操作来实现悲观锁。当数据库执行select for update时会获取被select中的数据行的行锁,因此其他并发执行的select for update如果试图选中同一行则会发生排斥(需要等待行锁被释放),因此达到锁的效果。select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。 这里需要注意的一点是不同的数据库对select for update的实现和支持都是有所区别的,例如oracle支持select for update no wait,表示如果拿不到锁立刻报错,而不是等待,mysql就没有no wait这个选项。另外mysql还有个问题是select for update语句执行中所有扫描过的行都会被锁上

Java的CAS乐观锁原理解析

血红的双手。 提交于 2020-01-07 00:20:23
CAS全称 Compare And Swap(比较与交换),在不使用锁的情况下实现多线程之间的变量同步。属于硬件同步原语,处理器提供了基本内存操作的原子性保证。juc包中的原子类就是通过CAS来实现了乐观锁。 CAS算法涉及到三个操作数: 需要读写的内存值 V。 进行比较的旧值A (期望操作前的值) 要写入的新值 B。 当且仅当 V 的值等于 A 时,CAS通过原子方式用新值B来更新V的值(“比较+更新”整体是一个原子操作),否则不会执行任何操作。 一般情况下,“更新”是一个不断重试的过程。 JAVA中的sun.misc.Unsafe类,提供了 compareAndSwapInt compareAndSwapLong 等方法实现CAS。 示例 J.U.C包内的原子操作封装类 看一下AtomicInteger的源码定义: public class AtomicInteger extends Number implements java.io.Serializable { private static final long serialVersionUID = 6214790243416807050L; // setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe =

乐观锁

别来无恙 提交于 2020-01-01 04:18:54
乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。而乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。 悲观锁(Pessimistic Lock),正如其名,具有强烈的独占和排他特性。它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。 来源: https://www.cnblogs.com/a-xu/p/8715969.html

悲观锁和乐观锁

≡放荡痞女 提交于 2019-12-29 07:49:56
悲观锁(Pessimistic Lock) 顾名思义,就是 很悲观 ,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型 数据库 里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。 我们认为 系统 中的并发更新会非常频繁,并且事务失败了以后重来的开销很大,这样以来,我们就需要采用真正意义上的锁来进行实现。悲观锁的基本思想就是每次一个事务读取某一条记录后,就会把这条记录锁住,这样其它的事务要想更新,必须等以前的事务提交或者回滚解除锁。 乐观锁(Optimistic Lock) 顾名思义,就是 很乐观 ,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。 我们认为系统中的事务并发更新不会很频繁,即使冲突了也没事,大不了重新再来一次。它的基本思想就是每次提交一个事务更新时,我们想看看要修改的东西从上次读取以后有没有被其它事务修改过,如果修改过,那么更新就会失败。 两种锁的比较 两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下

悲观锁、乐观锁

荒凉一梦 提交于 2019-12-29 07:49:47
悲观锁(Pessimistic Lock) 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型 数据库 里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。 我们认为 系统 中的并发更新会非常频繁,并且事务失败了以后重来的开销很大,这样以来,我们就需要采用真正意义上的锁来进行实现。悲观锁的基本思想就是每次一个事务读取某一条记录后,就会把这条记录锁住,这样其它的事务要想更新,必须等以前的事务提交或者回滚解除锁。 实现方式: 大多在数据库层面实现加锁操作,JDBC方式:在JDBC中使用悲观锁,需要使用select for update语句,e.g. <code class="language-sql hljs ">Select * from Account where ...(where condition).. for update</code> 乐观锁(Optimistic Lock) 顾名思义,就是 很乐观 ,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁 适用于多读的应用类型,这样可以提高吞吐量 ,像数据库如果提供类似于write

乐观锁与悲观锁原理及实现

久未见 提交于 2019-12-29 07:49:17
一、乐观锁 总是认为不会产生并发问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS操作实现。 version方式 :一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。 核心SQL代码: update table set x=x+1, version=version+1 where id=#{id} and version=#{version}; CAS操作方式 :即compare and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作,即不断的重试。 二、悲观锁 总是假设最坏的情况,每次取数据时都认为其他线程会去修改,所以都会加锁(读锁、写锁、行锁等),当其他线程想要访问数据时,都需要阻塞挂起等待。可以依靠数据库实现,如行锁、读锁和写锁等,都是在操作之前加锁

乐观锁与悲观锁

拥有回忆 提交于 2019-12-26 12:23:23
在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突。这就是著名的并发性问题。 典型的冲突有: l 丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。例如:用户A把值从6改为2,用户B把值从2改为6,则用户A丢失了他的更新。 l 脏读:当一个事务读取其它完成一半事务的记录时,就会发生脏读取。例如:用户A,B看到的值都是6,用户B把值改为2,用户A读到的值仍为6。 并发控制机制 最常用的处理多用户并发访问的方法是加锁。当一个用户锁住数据库中的某个对象时,其他用户就不能再访问该对象。加锁对并发访问的影响体现在锁的粒度上。比如,放在一个表上的锁限制对整个表的并发访问;放在数据页上的锁限制了对整个数据页的访问;放在行上的锁只限制对该行的并发访问。可见行锁粒度最小,并发访问最好,页锁粒度最大,表锁介于2者之间。 悲观锁:假定会发生并发冲突, 屏蔽一切可能违反数据完整性的操作。[1] 悲观锁假定其他用户企图访问或者改变你正在访问、更改的对象的概率是很高的,因此在悲观锁的环境中,在你开始改变此对象之前就将该对象锁住,并且直到你提交了所作的更改之后才释放锁。悲观的缺陷是不论是页锁还是行锁,加锁的时间可能会很长,这样可能会长时间的限制其他用户的访问,也就是说悲观锁的并发访问性不好。 乐观锁:假设不会发生并发冲突, 只在提交操作时检查是否违反数据完整性。[1]