我对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);
}
}
}
答案 0 :(得分:1)
你最好锁定authenticatedUser.getUserName ().intern ()
因为保证一旦两个字符串按内容相同,intern ()
将为它们返回相同的对象。
此外,如果系统中有保证,只有一个具有特定用户名的AuthenticatedUser
类实例,则可以直接锁定authenticatedUser
。
答案 1 :(得分: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,就可以检查它是否已被复制并释放锁定或执行复制。