休眠和锁定

时间:2011-09-19 11:01:42

标签: java hibernate locking

我试图排除两个读取线程通过hibernate读取相同的记录。我的SSCCE如上所述,但是两个线程都可以读取对象,而我期望Thread-2会抛出异常。

Store类可以轻松创建Sessions。

我现在正在使用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

1 个答案:

答案 0 :(得分:1)

LockMode.Read是一个共享锁,因此具有该锁定模式的所有读取都能够在不阻塞的情况下从同一个源读取。

我认为你想要的是一个使用LockMode.PESSIMISTIC_WRITE的独占锁。 HSQLDB支持这种类型的锁(docs

我还要在两个线程之间添加Thread.yield(),以允许第一个线程实际启动,否则第二个线程可能在您定义的第一个线程之前开始。


我认为HSQLDB没有锁定超时,因此当线程等待锁定超过给定时间时会抛出异常。你会看到T2中的ses.load将始终发生在t1的ses.close之后。

如果你手头有一个mysql数据库,可以使用innodb_lock_wait_timeout = 2更新配置,这会导致数据库在2秒后抛出锁定超时。