何时在GAE中抛出ConcurrentModificationException?

HRJ*_*HRJ 6 java transactions google-cloud-datastore

我正在阅读有关交易的官方GAE 文档,我无法理解何时ConcurrentModificationException抛出.

看看我在这里复制粘贴的一个例子:

int retries = 3;
while (true) {
    Transaction txn = datastore.beginTransaction();
    try {
        Key boardKey = KeyFactory.createKey("MessageBoard", boardName);
        Entity messageBoard = datastore.get(boardKey);

        long count = (Long) messageBoard.getProperty("count");
        ++count;
        messageBoard.setProperty("count", count);
        datastore.put(messageBoard);

        txn.commit();
        break;
    } catch (ConcurrentModificationException e) {
        if (retries == 0) {
            throw e;
        }
        // Allow retry to occur
        --retries;
    } finally {
        if (txn.isActive()) {
            txn.rollback();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,对数据存储区的所有写入(在此示例中)都包含在事务中.那为什么会ConcurrentModificationException抛出?

如果某个未包含在事务中的其他代码更新了上述代码正在修改的同一实体,是否会发生这种情况?如果我确保更新实体的所有代码始终包含在事务中,是否保证我不会获得ConcurrentModificationException?

HRJ*_*HRJ 1

我在 GAE 邮件列表中找到了答案。

我对 GAE 中的事务如何运作有一个误解。我曾想象开始一个事务将锁定对数据存储的任何并发更新,直到事务提交。这将是一场性能噩梦,因为所有更新都会阻止此事务,但我很高兴事实并非如此。

相反,发生的情况是,第一个更新获胜,如果在后续更新中检测到冲突,则会引发异常。

一开始这让我感到惊讶,因为这意味着许多事务将需要重试逻辑。但它似乎与 PostgreSQL 的“可序列化隔离”级别语义相似,尽管在 PostgreSQL 中您也可以选择锁定单个行和列。