乐观锁使用经验一则

<转自http://fantasytree.iteye.com/blog/704953>
假设需要用乐观锁来实现一个物品数量增减操作的原子性,可以这样子做:(框架使用spring和hibernate)

Java代码 
@Entity 
@Table(name="tbl_gift") 
public class Gift { 
    ... 
     
    //乐观锁 
    @Version 
    private Long version; 
 
    ... 


Java代码 
@Transactional(readOnly=false, propagation=Propagation.REQUIRED) 
public void exchange(){ 
    ... 
    修改gift的剩余数量(采用乐观锁); 
    ... 



以上这段代码在并发修改下会有2种报错(org.hibernate.StaleObjectStateException)的可能:
(1)函数内(提交事务前);
     线程1开事务->读礼品id=1,得version=0 -> 改剩余数量和version -> 提交事务
     线程2开事务->读礼品id=1,得version=0 ----------------------------------->改剩余数量和version(出错)

(2)函数外(提交事务后);
     线程1开事务->读礼品id=1,得version=0 -> 改剩余数量和version -> 提交事务
     线程2开事务->读礼品id=1,得version=0 -> 改剩余数量和version ------------>提交事务(出错)

添加重试:
Java代码 
@Transactional(readOnly=false, propagation=Propagation.REQUIRED) 
public void exchange(){ 
    ... 
    修改gift的剩余数量(采用乐观锁); 
    ... 

public void exchange2() throws Exception { 
    try { 
        exchange(); 
    } catch(org.hibernate.StaleObjectStateException e) { 
        exchange(); 
    } 


注意:是使用一个没有事务的方法包住一个有事务的方法。此外,如果在使用OpenSessionInView的情况下,这种重试的方法是没有作用的。

猜你喜欢

转载自yypiao.iteye.com/blog/1508660