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

2つの文字列の内容が同一になると、同じオブジェクトが返さauthenticatedUser.getUserName ().intern ()れることが保証されているため、ロックをオンにすることをお勧めします。intern ()

また、システムで特定のユーザー名を持つクラスのインスタンスが1つしかないことが保証されている場合は、をAuthenticatedUser直接ロックできますauthenticatedUser

于 2013-02-04T17:45:57.660 に答える
1

あなたが言及したように、authenticatedUser.getUserName() での同期は、authenticatedUser のインスタンスが複数ある可能性があるため機能しません。同じ authenticatedUser データを読み取る 2 つのスレッドは、異なる EntityManager コンテキストから読み取られた場合、異なるインスタンスを取得します。これを回避するには、doReplication メソッドを try/catch ブロックでラップして (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 に答える