1

我需要一个带有 ObjectDB 的原子计数器,但以下代码无法按预期工作:

    final EntityManagerFactory emf = Persistence.createEntityManagerFactory("test.odb");
    EntityManager em = emf.createEntityManager();
    Point p = new Point(0, 0);
    em.getTransaction().begin();
    em.persist(p);
    em.getTransaction().commit();
    em.close();
    final CountDownLatch l = new CountDownLatch(100);
    for (int i = 0; i < 100; i++) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                EntityManager em = emf.createEntityManager();
                em.getTransaction().begin();
                //Query q = em.createQuery("UPDATE Point SET x = x + 1");
                Query query = em.createQuery("UPDATE Point SET x = x + 1");
                query.executeUpdate();
                em.getTransaction().commit();
                em.close();
                l.countDown();                    
            }
        });
        t.start();
    }
    l.await();
    em = emf.createEntityManager();
    TypedQuery<Point> myquery = em.createQuery("SELECT p from Point p", Point.class);
    List<Point> results = myquery.getResultList();
    System.out.println("X coordiate is: " + results.get(0).getX());
    em.close();

它应该打印出 X 坐标是 100。但实际上,它没有。

我的代码有什么问题?

4

2 回答 2

0

您可以通过以下方式之一修复您的代码:

同步您的更新查询,因此它们将按顺序执行,而不是同时执行:

synchronized (lock) {
    em.createQuery("UPDATE Point SET x = x + 1").executeUpdate();
}

您的锁对象必须是一个由所有线程共享的对象。

或者,通过设置悲观锁定超时来使用 ObjectDB / JPA 锁定,例如:

Map<String, Integer> properties =
    Collections.singletonMap("javax.persistence.lock.timeout", 1000);
EntityManagerFactory emf =
    Persistence.createEntityManagerFactory(
        "objectdb:$objectdb/db/test.tmp;drop", properties);

然后用带锁和更新的检索替换 UPDATE 查询:

Point point = em.find(Point.class, 1, LockModeType.PESSIMISTIC_WRITE);
point.setX(point.getX() + 1);
于 2014-04-22T13:05:32.830 回答
0

更好地为 Point 创建一个 DAO 类,并用函数包装persist(), merge()... 函数synchronized

或者,AtomicIntegerwithgetAndIncrement()应该可以解决您的问题,而无需同步和锁定。

于 2014-07-23T14:54:42.687 回答