应用场景:现有一个表Article(帖子),其中有一个字段visit_amount表示这个帖子被浏览过多少次。
现在做一个实验,开两个线程做同一件事情,就是:取出原有的浏览次数,然后加一,再存回数据库。每个线程把这个动作重复10次。
设想的结果:如果浏览次数的初始值是0的话,那么程序运行完毕后,浏览次数应该增长到20。
-
- package com.javaye;
-
- import org.hibernate.class=hilite1>LockMode;
- import org.hibernate.Session;
- import org.hibernate.Transaction;
-
- import com.javaye.models.Article;
-
- public class Main {
-
-
- private static void update(){
- Session session = HibernateSessionFactory.getSession();
- Transaction tx = session.beginTransaction();
- Article art = (Article) session.load(Article.class, 1);
- art.setVisitAmount(art.getVisitAmount()+1);
- session.save(art);
- tx.commit();
-
-
- }
-
- private static void work(){
- for(int i=0;i<10;i++){
- System.out.println(Thread.currentThread().getName()+":"+(i+1)+"times.");
- update();
- }
- }
-
- public static void main(String[] args) throws Exception{
- Thread t1 = new Thread(
- new Runnable(){
- public void run(){
- work();
- }
- }
- );
-
- Thread t2 = new Thread(
- new Runnable(){
- public void run(){
- work();
- }
- }
- );
- t1.setName("Thread1");
- t2.setName("Thread2");
- t1.setDaemon(true);
- t2.setDaemon(true);
- t1.start();
- t2.start();
- t1.join();
- t2.join();
-
- }
- }
package com.javaye;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.javaye.models.Article;
public class Main {
private static void update(){
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
Article art = (Article) session.load(Article.class, 1);
art.setVisitAmount(art.getVisitAmount()+1);
session.save(art);
tx.commit();
}
private static void work(){
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+":"+(i+1)+"times.");
update();
}
}
public static void main(String[] args) throws Exception{
Thread t1 = new Thread(
new Runnable(){
public void run(){
work();
}
}
);
Thread t2 = new Thread(
new Runnable(){
public void run(){
work();
}
}
);
t1.setName("Thread1");
t2.setName("Thread2");
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
t1.join();
t2.join();
}
}
上面是第一个版本,结果测试的结果发现没有实现事务的隔离性,每次的结果是随机的,要么是10要么是11或12。
然后,我进行了修改,加上了session.evict(art)来清空缓存,然后发现结果变得好一些了,但是结果并不总是20,有时候是19或18。真奇怪。
再后来,把load语句改为:
- Article art = (Article) session.load(Article.class, 1,class=hilite1>LockMode.UPGRADE);
Article art = (Article) session.load(Article.class, 1,LockMode.UPGRADE);
经过多次测试,结果总为20,实现了事务的隔离性。
最终work的代码如下:
- package com.javaye;
-
- import org.hibernate.class=hilite1>LockMode;
- import org.hibernate.Session;
- import org.hibernate.Transaction;
-
- import com.javaye.models.Article;
-
- public class Main {
-
- private static void insert(){
- Session session = HibernateSessionFactory.getSession();
- Transaction tx = session.beginTransaction();
- Article art = new Article();
- art.setTitle("AAA");
- art.setVisitAmount(0);
- session.saveOrUpdate(art);
- tx.commit();
- }
-
- private static void update(){
- Session session = HibernateSessionFactory.getSession();
- Transaction tx = session.beginTransaction();
- Article art = (Article) session.load(Article.class, 1,class=hilite1>LockMode.UPGRADE);
- art.setVisitAmount(art.getVisitAmount()+1);
- session.save(art);
- tx.commit();
- session.evict(art);
-
- }
-
- private static void work(){
- for(int i=0;i<10;i++){
- System.out.println(Thread.currentThread().getName()+":"+(i+1)+"times.");
- update();
- }
- }
-
- public static void main(String[] args) throws Exception{
- Thread t1 = new Thread(
- new Runnable(){
- public void run(){
- work();
- }
- }
- );
-
- Thread t2 = new Thread(
- new Runnable(){
- public void run(){
- work();
- }
- }
- );
- t1.setName("Thread1");
- t2.setName("Thread2");
- t1.setDaemon(true);
- t2.setDaemon(true);
- t1.start();
- t2.start();
- t1.join();
- t2.join();
-
- }
- }
package com.javaye;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.javaye.models.Article;
public class Main {
private static void insert(){
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
Article art = new Article();
art.setTitle("AAA");
art.setVisitAmount(0);
session.saveOrUpdate(art);
tx.commit();
}
private static void update(){
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
Article art = (Article) session.load(Article.class, 1,LockMode.UPGRADE);
art.setVisitAmount(art.getVisitAmount()+1);
session.save(art);
tx.commit();
session.evict(art);
}
private static void work(){
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+":"+(i+1)+"times.");
update();
}
}
public static void main(String[] args) throws Exception{
Thread t1 = new Thread(
new Runnable(){
public void run(){
work();
}
}
);
Thread t2 = new Thread(
new Runnable(){
public void run(){
work();
}
}
);
t1.setName("Thread1");
t2.setName("Thread2");
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
t1.join();
t2.join();
}
}
查了一下文档,
LockMode.UPGRADE是最高的锁级别了,如果换用其他的级别呢?我测试了LocMode.READ,发现还是不正确,用
LockMode.WRITE的时候竟然抛异常。。
阅读(935) | 评论(0) | 转发(0) |