Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1995005
  • 博文数量: 606
  • 博客积分: 9991
  • 博客等级: 中将
  • 技术积分: 5725
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-17 19:07
文章分类

全部博文(606)

文章存档

2011年(10)

2010年(67)

2009年(155)

2008年(386)

分类:

2008-07-29 22:40:47

应用场景:现有一个表Article(帖子),其中有一个字段visit_amount表示这个帖子被浏览过多少次。
现在做一个实验,开两个线程做同一件事情,就是:取出原有的浏览次数,然后加一,再存回数据库。每个线程把这个动作重复10次。

设想的结果:如果浏览次数的初始值是0的话,那么程序运行完毕后,浏览次数应该增长到20。

Java代码 复制代码
  1.   
  2. package com.javaye;   
  3.   
  4. import org.hibernate.class=hilite1>LockMode;   
  5. import org.hibernate.Session;   
  6. import org.hibernate.Transaction;   
  7.   
  8. import com.javaye.models.Article;   
  9.   
  10. public class Main {   
  11.        
  12.   
  13.     private  static void update(){   
  14.         Session session = HibernateSessionFactory.getSession();   
  15.         Transaction tx =  session.beginTransaction();   
  16.         Article art = (Article) session.load(Article.class1);   
  17.         art.setVisitAmount(art.getVisitAmount()+1);   
  18.         session.save(art);   
  19.         tx.commit();   
  20.            
  21.            
  22.     }   
  23.        
  24.     private static void work(){   
  25.         for(int i=0;i<10;i++){   
  26.             System.out.println(Thread.currentThread().getName()+":"+(i+1)+"times.");   
  27.             update();   
  28.         }   
  29.     }   
  30.        
  31.     public static void main(String[] args) throws Exception{   
  32.         Thread t1 = new Thread(   
  33.             new Runnable(){   
  34.                 public void run(){   
  35.                     work();   
  36.                 }   
  37.             }   
  38.         );   
  39.            
  40.         Thread t2 = new Thread(   
  41.                 new Runnable(){   
  42.                     public void run(){   
  43.                         work();   
  44.                     }   
  45.                 }   
  46.         );   
  47.         t1.setName("Thread1");   
  48.         t2.setName("Thread2");   
  49.         t1.setDaemon(true);   
  50.         t2.setDaemon(true);   
  51.         t1.start();   
  52.         t2.start();   
  53.         t1.join();   
  54.         t2.join();   
  55.            
  56.     }   
  57. }  


上面是第一个版本,结果测试的结果发现没有实现事务的隔离性,每次的结果是随机的,要么是10要么是11或12。

然后,我进行了修改,加上了session.evict(art)来清空缓存,然后发现结果变得好一些了,但是结果并不总是20,有时候是19或18。真奇怪。

再后来,把load语句改为:
Java代码 复制代码
  1. Article art = (Article) session.load(Article.class1,class=hilite1>LockMode.UPGRADE);  


经过多次测试,结果总为20,实现了事务的隔离性。

最终work的代码如下:
Java代码 复制代码
  1. package com.javaye;   
  2.   
  3. import org.hibernate.class=hilite1>LockMode;   
  4. import org.hibernate.Session;   
  5. import org.hibernate.Transaction;   
  6.   
  7. import com.javaye.models.Article;   
  8.   
  9. public class Main {   
  10.        
  11.     private static void insert(){   
  12.         Session session = HibernateSessionFactory.getSession();   
  13.         Transaction tx = session.beginTransaction();   
  14.         Article art = new Article();   
  15.         art.setTitle("AAA");   
  16.         art.setVisitAmount(0);   
  17.         session.saveOrUpdate(art);   
  18.         tx.commit();   
  19.     }   
  20.        
  21.     private  static void update(){   
  22.         Session session = HibernateSessionFactory.getSession();   
  23.         Transaction tx =  session.beginTransaction();   
  24.         Article art = (Article) session.load(Article.class1,class=hilite1>LockMode.UPGRADE);   
  25.         art.setVisitAmount(art.getVisitAmount()+1);   
  26.         session.save(art);   
  27.         tx.commit();   
  28.         session.evict(art);   
  29.            
  30.     }   
  31.        
  32.     private static void work(){   
  33.         for(int i=0;i<10;i++){   
  34.             System.out.println(Thread.currentThread().getName()+":"+(i+1)+"times.");   
  35.             update();   
  36.         }   
  37.     }   
  38.        
  39.     public static void main(String[] args) throws Exception{   
  40.         Thread t1 = new Thread(   
  41.             new Runnable(){   
  42.                 public void run(){   
  43.                     work();   
  44.                 }   
  45.             }   
  46.         );   
  47.            
  48.         Thread t2 = new Thread(   
  49.                 new Runnable(){   
  50.                     public void run(){   
  51.                         work();   
  52.                     }   
  53.                 }   
  54.         );   
  55.         t1.setName("Thread1");   
  56.         t2.setName("Thread2");   
  57.         t1.setDaemon(true);   
  58.         t2.setDaemon(true);   
  59.         t1.start();   
  60.         t2.start();   
  61.         t1.join();   
  62.         t2.join();   
  63.            
  64.     }   
  65. }  


查了一下文档,LockMode.UPGRADE是最高的锁级别了,如果换用其他的级别呢?我测试了LocMode.READ,发现还是不正确,用LockMode.WRITE的时候竟然抛异常。。
阅读(935) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~