我试图排除两个读取线程通过 hibernate 读取同一记录。我的 SSCCE 如上所述,但是两个线程都可以读取该对象,而我期望 Thread-2 会抛出异常。
Store 类是我用来轻松创建 session 的类。
我现在正在使用 HSQLDB 进行测试,也许没有可用的锁定?
更新按照奥古斯托的建议做了,但还是一样。 Thread-2 应该抛出异常 (?)
new Thread(new Runnable() { // Thread-1
@Override
public void run() {
Session ses = Store.$.ses();
Object x = ses.load(Client.class, 1l,
new LockOptions(LockMode.PESSIMISTIC_WRITE));
System.err.println("T1 :"+(x==null));
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
}
ses.close();
}
}).start();
Thread.yield();
new Thread(new Runnable() { // Thread-2
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
}
Session ses = Store.$.ses();
Object x = ses.load(Client.class, 1L,
new LockOptions(LockMode.PESSIMISTIC_WRITE).setTimeOut(1));
System.err.println("T2 :"+(x==null));
ses.close();
}
}).start();
<小时/>
Output:
T1: false
t2: false
最佳答案
LockMode.Read 是共享锁,因此具有该锁模式的所有读取都能够从同一源读取而不会阻塞。
我认为你想要的是一个独占锁,它使用LockMode.PESSIMISTIC_WRITE。并且HSQLDB支持这种类型的锁( docs )
我还要添加Thread.yield()
在两个线程之间,以允许第一个线程实际启动,否则第二个线程可能会在您定义的第一个线程之前启动。
我认为 HSQLDB 没有锁超时,因此当线程等待锁的时间超过给定时间时会抛出异常。您将看到的是 ses.load
T2 中总是发生在 ses.close
之后从 t1 开始。
如果你手头有mysql数据库,可以用 innodb_lock_wait_timeout = 2
更新配置这将导致数据库在 2 秒后抛出锁定超时。
关于java - hibernate 和锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7469898/