1

我对Java中的多线程不是很有经验。我想要的是为代码块设置一个锁。就我而言,我想避免乐观锁定异常,同时为某个用户进行一些同步。该方法replicateUser可以由同一用户的多个线程调用。但不能保证,那authenticatedUser总是同一个相同的对象。

那么我怎样才能有效地锁定这个部分呢?我不想要的是,该部分已锁定所有线程,但仅适用于具有相同用户的线程。我可以使用下面的示例对字符串对象进行锁定getUserName()吗?

private void replicateUser(AuthenticatedUser authenticatedUser) {
    //
    // How to synchronize the following block correctly?
    //
    synchronized (authenticatedUser.getUserName()) {
        User dbUser = userRepository.findOne(authenticatedUser.getUserName());
        if (!checkIsUserReplicated(authenticatedUser, dbUser)) {
            doReplication(dbUser);
        }
    }
}
4

2 回答 2

1

您最好锁定,authenticatedUser.getUserName ().intern ()因为一旦两个字符串的内容相同,就可以保证intern ()为它们返回相同的对象。

此外,如果在您的系统中保证只有一个AuthenticatedUser具有特定用户名的类实例,那么您可以直接锁定authenticatedUser.

于 2013-02-04T17:45:57.660 回答
1

正如您所提到的,在 authenticatedUser.getUserName() 上同步将不起作用,因为您可能有多个 authenticatedUser 实例。如果从不同的 EntityManager 上下文中读取,两个线程读取相同的 authenticatedUser 数据将获得不同的实例。为了解决这个问题,您可以通过使用 try/catch 块包装 doReplication 方法来解决偶尔出现的乐观锁异常,然后检查更改是否由另一个线程(使用 em.refresh)进行,或者您可以切换到使用此处描述的悲观锁定:http: //wiki.eclipse.org/EclipseLink/Examples/JPA/Locking#Pessemistic_Locking http://wiki.eclipse.org/EclipseLink/Examples/JPA/PessimisticLocking

锁定 authenticatedUser 后,您可以检查它是否已被复制并释放锁定或执行复制。

于 2013-02-04T18:44:56.787 回答