Object lock = new Object();
private void transactionCollision() throws InterruptedException {
Session session = HibernateSessionFactory.getSession();
User ben = (User)session.get(User.class, new Long(1));
new BranchThread().start();
synchronized (lock) {//Before being notify the obj would be locked.
lock.wait();
}
session.beginTransaction();
ben.setNickName(ben.getNickName() + "do sth_a");
session.getTransaction().commit();
session.close();
}
private class BranchThread implements Runnable {
public void run() {
synchronized (lock) {
try {
lock.wait(2*1000);//wait 2 seconds the ensure
// the main thread would read the dirt data.
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.notifyAll();
Session session = HibernateSessionFactory.getSession();
User ben = (User) session.get(User.class, new Long(1));
session.beginTransaction();
ben.setNickName(ben.getNickName() + "do sth_b");
session.getTransaction().commit();
session.close();
}
}
public void start() {
new Thread(this).start();
}
}
典型的更新丟失問題,當然這是利用synchronized模擬的極端情況,但極端情況並不代表不發生。解決方案之一是加入樂觀鎖。具體操作過程如下:
entity加入一個數字類型屬性,該屬性與業務邏輯無關,被hibernate用作版本戳,具體如下:
private Integer version = new Integer(0);
重新配置hbm.xml文件,將該字段應慎到數據庫中
<id name="oid" type="long">
<generator class="native" />
</id>
<version name="version" type="int" />
配置之後在執行上述語句會拋出:org.hibernate.StaleObjectStateException
參考文章:
http://www.360doc.com/showWeb/0/0/415808.aspx
http://www.360doc.com/showWeb/0/0/415808.aspx
以上屬於樂觀鎖解決方案,還可以考慮悲觀所解決方案;但悲觀所解決方案需要一個與數據庫的常鏈接,所以我認爲,作爲b/s項目,利用悲觀所解決併發問題是不合理的,因爲你無法保證一個常連接。