1


ある種の「facebook like」機能を備えたアプリケーションを開発しています。ユーザーが公開したコンテンツが「いいね」されるたびに、句読点が増えます。このアプリは社内の多数のユーザーが使用するため、同じ行への多数の同時更新が予想されます。

簡略化されたコード

ユーザー句読点表

Punctuation(
    userId NVARCHAR2(32),
    value NUMBER(10,0)
)/


Java コード

public class Punctuation(){
    private String userId;
    private int value;

    public Punctuation(final String userId, final int value){
            this.userId = userId;
            this.value = value;
    }

    public String getUserId();
    public int getValue();

}

//simplified code
public final class PunctuationController{

    private PunctuationController(){}

    public static void addPunctuation(final Punctuation punctuation){

        final Transaction transaction = TransactionFactory.createTransaction();
        Connection conn = null;
        PreparedStatment statment = null;
        try{
                synchronized(punctuation){
                    transaction.begin();
                    conn = transaction.getConnection();
                    statment = conn.preparedStatment("UPDATE Punctuation SET value = value + ? where userId = ?");
                    statment.setString('1', punctuation.getUserId());
                    statment.setInt('2', punctuation.getValue());
                    transaction.commit();
                }
        }catch (Exception e){
                transaction.rollback();
        }finally{
                transaction.dispose();
                if(statment !=null){
                        statment.close();
                }
        }
}



更新中のデッドロックを恐れています。Oracle では、単一のクエリで合計を作成できます。値を取得して、新しい値で更新するために 2 番目のクエリを作成する必要はありません。これは良いことです。また、ここで他の投稿を読んでいると、同期ブロックを作成してオブジェクトをロックし、Java に異なるスレッド間の同期を処理させるように言われました。メソッドが受け取る句読点インスタンスを選択します。このようにして、ユーザーと値のさまざまな組み合わせがこのメソッドへの同時アクセスを許可すると想像しますが、同じ値を持つインスタンスをブロックします (句読点に equals() を実装する必要がありますか?

)データベースは、Oracle 10g、Server Weblogic 11g、Java 6、および Linux です (どのフレーバーかはわかりません)。

前もって感謝します!

4

2 に答える 2

3

同期戦略が間違っています。synchronized括弧の間のオブジェクトの固有のロックを使用します。Punctuation同じ を参照しているために等しいと見なす可能性のある2 つのインスタンスがある場合user_id、Java は気にしません。2 つのオブジェクト、つまり 2 つのロック、したがって相互排除はありません。

上記の がなく、デッドロックが発生する可能性がある理由が本当にわかりませんsynchronized。テーブル内の単一の行を更新しています。1 つが user1、次に user2 を更新し、もう 1 つが user2、次に user1 を更新する 2 つの同時トランザクションがある場合、デッドロックが発生する可能性があります。しかし、その場合でも、データベースはデッドロックを検出し、トランザクションの 1 つに対して例外をスローします。

于 2012-07-31T10:44:53.817 に答える
0

楽観的なロックパターンを使用する必要があります。詳細については、こちらをご覧くださいhttp://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/The_CMP_Engine-Optimistic_Locking.html

そしておそらく、このhttp://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/The_CMP_Engine-Optimistic_Locking.htmlは、より低レベルの詳細です

楽観的ロックを使用して同時発生の問題を特定した後、再試行することをお勧めします。何をすべきかを完全に制御できます。

于 2012-07-31T10:45:14.923 に答える