2

私の質問は、Java でのオブジェクト インスタンスのロックに関するものです。複数のスレッドから同時に呼び出すことができる次のメソッドがあります。一度に 1 つのスレッドだけが 1 つのインスタンスにアクセスしている限り、同時処理を許可したいので、オブジェクト インスタンスをロックすることにしました。

私の単純化されたコードは、基本的にローカル変数をロックしているこのようなものになります。これは私が必要としているものを本当に満たしてくれるでしょうか?変更される可能性のあるオブジェクトを決してロックしないようにするための提案を読んでいましたが、結局これが私がやっていることなのかどうか突然確信が持てなくなりました!

ありがとう!

編集:

親愛なる...投稿のためにコードを単純化しようとする試みが少し誤解を招く可能性があることに気づきました。

以前「getInstance」と呼んでいたメソッドの名前を別のもの (「getFromMap」) に変更して、メソッド呼び出しがハッシュマップ内のオブジェクトへの参照を返すカスタム コードであることを示します。

前の答えはまだ有効ですか?混乱をお詫びします!

public boolean processInput(...) {
if(message == 1) {
    Class_0 context = (Class_0)Class_0.getFromMap("xyz");
    synchronized(context) {
        context.setContextParams("abc");
       context.evaluateContextRules(message, this);
    }
} else if(message == 2) {
    Class_1 context = (Class_1)Class_1.getFromMap("efg");
    synchronized(context) {
        context.setContextParams("abc");
        context.evaluateContextRules(message, this);
    }
}
.....
}
4

5 に答える 5

3

オブジェクト型の変数は、オブジェクトへの単なる参照です。ロックされているのはオブジェクトであり、参照ではありません。このようなロックは、関連するデータを読み書きする可能性のあるすべてのクライアントが、同じオブジェクトのロックを保持している場合にのみそうすることに同意する場合にのみ有効です。ローカル変数かどうかは問題ではありません。全員が同じオブジェクトをロックとして使用しているかどうかです。

ここで、あなたのオブジェクトはある種の工場から来ているようです。XgetInstance(X)の特定の値に対して常に同じオブジェクトを返す場合は、おそらく問題ありません。

于 2012-07-30T13:30:26.787 に答える
1

あなたの質問には、このコードが完全にスレッドセーフであるかどうかを確認するのに十分な「コンテキスト」(しゃれは意図されていません) がありません。

messageただし、1)がローカル変数であり、2) コンテキスト オブジェクトにアクセスまたは更新するすべてのものがオブジェクトの同期中に行われると仮定すると、このフラグメントのコードはスレッドセーフです。


変更される可能性のあるオブジェクトを決してロックしないようにするための提案を読んでいましたが、結局これが私がやっていることなのかどうか突然確信が持てなくなりました!

あなたが心配する必要があるのは、次のようなものです。

public class Foo {
    // some state variables

    public Object lock = new Object();

    public void doSomething(...) {
        synchronized (lock) {
            ....
        }
    }
}

これは潜在的に安全ではありません。何かがlock適切なタイミングで の値を変更した場合、同じFooインスタンスに対する 2 つの操作が異なるロック オブジェクトを使用して同期される可能性があります。Fooこれにより、状態が適切に同期されない操作が発生する可能性があります。

あなたの例では、同期contextはコンテキストオブジェクト自体の操作用であるように見えるため、上記の問題は当てはまりません。

于 2012-07-30T13:34:41.490 に答える
1

仮定して:

Class_1 context = (Class_1)TestForInternals_0.getInstance("efg");

単に既存のオブジェクトへの参照を取得し、新しいインスタンスを作成しない場合、そのオブジェクトのモニターはロックされ、実行中の操作は有効になります。

于 2012-07-30T13:28:42.280 に答える
0

あなたが行った変更がメソッドcontextによって返されるものに影響を与えない限り、あなたのコードは機能しますgetInstance

于 2012-07-30T13:33:51.233 に答える
0

私が理解しているように、メソッド processInput が呼び出されており、同期されたブロックが確実に、 context.evaluateContextRules(...) が1つのスレッドでのみ実行されます。

それがあなたの目標なら、はい、あなたのコードはそれを行います。

他の人は、オブジェクトへの参照ではなく、オブジェクトをロックしていることを確認する必要があると述べました。コードを見ると、メソッドを呼び出すのとまったく同じオブジェクトで同期しているので、問題にはなりません。

于 2012-07-30T13:54:44.930 に答える