首页 > 代码库 > 乐观锁和悲观锁
乐观锁和悲观锁
锁需要解决的问题:多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突。
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。 悲观锁假定其他用户企图访问或者改变你正在访问、更改的对象的概率是很高的,因此在悲观锁的环境中,在你开始改变此对象之前就将该对象锁住,并且直到你提交了所作的更改之后才释放锁。悲观的缺陷是不论是页锁还是行锁,加锁的时间可能会很长,这样可能会长时间的限制其他用户的访问,也就是说悲观锁的并发访问性不好。
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。乐观锁不能解决脏读的问题。 乐观锁则认为其他用户企图改变你正在更改的对象的概率是很小的,因此乐观锁直到你准备提交所作的更改时才将对象锁住,当你读取以及改变该对象时并不加锁。可见乐观锁加锁的时间要比悲观锁短,乐观锁可以用较大的锁粒度获得较好的并发访问性能。但是如果第二个用户恰好在第一个用户提交更改之前读取了该对象,那么当他完成了自己的更改进行提交时,数据库就会发现该对象已经变化了,这样,第二个用户不得不重新读取该对象并作出更改。这说明在乐观锁环境中,会增加并发用户读取对象的次数。
应用方式:
一般是基于数据版本(Version)记录机制实现,即在数据库表增加一个 “version” 字段来实现(使用自增长的整数表示数据版本号,每次更新时将版本号加一)。
每当读取出数据时,将版本号一同读出,之后更新时,对此版本号加一。
此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号等于数据库表当前版本号加一(cur.version = sql.version+1 或者提交的数据版本号(version)大于数据库表当前版本号),则予以更新,否则认为是过期数据。
java中Hibernate 支持两种锁机制:即通常所说的 悲观锁(Pessimistic Locking )和 乐观锁(Optimistic Locking ) 。Hibernate自带实现方式:在使用乐观锁的字段前加annotation: @Version, Hibernate在更新时自动校验该字段。
乐观锁和悲观锁