4

これらの例の違いを説明できる人はいますか?

例 # 1。

public class Main {

    private Object lock = new Object();
    private MyClass myClass = new MyClass();

    public void testMethod() {
        // TODO Auto-generated method stub
        synchronized (myClass) {
            // TODO: modify myClass variable
        }
    }

}

例 2。

package com.test;

public class Main {

    private MyClass myClass = new MyClass();
    private Object lock = new Object();

    public void testMethod() {
        // TODO Auto-generated method stub

        synchronized (lock) {
            // TODO: modify myClass variable
        }
    }

}

変数を変更するときに同期に注意する必要がある場合、モニター ロックとして何を使用すればよいですか?

4

6 に答える 6

3

ステートメントの同期は、オブジェクトの変数を変更するときに役立ちます。

myClassオブジェクトをロックしたいので、変数を変更していmyClassます。何かを変更する場合は、オブジェクトlockをロックする必要がありlockます。

例 2 では、ナンセンスなオブジェクトを変更していますがmyClass、ロックしています。lock

于 2013-02-06T17:57:58.850 に答える
3

「漏れやすい抽象化」を意図したものではないと仮定するとMain、最初の例と 2 番目の例の違いは最小限です。

インスタンスにはフィールドがなく、したがって小さいObjectため、他のクラスよりもを使用する方がよい場合があります。Objectそして、 -as-lock イディオムは、変数がロックとしてのみ使用されることを意図してObjectいることを明確にします。lock

そうは言っても、他の誰も見ることのないオブジェクトをロックすることには明確な利点があります。(例: ) でMain同期するメソッドの問題点は、他の無関係なコードが、無関係な目的で同期している可能性があることです。専用(プライベート)ロックオブジェクトで同期することにより、その可能性を回避できます。Mainthis


コメントに応じて:

2 つのケースには大きな違いがあります。最初に、操作したいオブジェクトをロックしています。2 番目の例では、操作対象のオブジェクトと明確な関係がない他のオブジェクトをロックしています。2 番目のケースでは、保護している既存のインスタンスを使用するのではなく、(そうでなければ未使用の) オブジェクトを割り当てる必要があるため、より多くのスペースが必要になります。

あなたは間違った仮定をしていると思います-それMyClassは保護が必要なデータ構造です。実際、質問はそうは言っていません。実際、この例の書き方は、ロックがMainクラス全体を保護することを意図していることを暗示しています...その状態の一部だけではありません。そして、その文脈では、明らかなつながりがあります...

をロックしたほうがよい唯一のケースは、 が漏れやすい抽象化であり、他のコードがその参照を取得できるようにMyClassする場合です。特にマルチスレッド アプリでは、これは悪い設計です。 MainmyClass

改訂履歴に基づいて、それはOPの意図ではないと確信しています.

于 2013-02-06T17:54:43.117 に答える
2

最初のケースでは、このメソッド内でのみ認識されているオブジェクトをロックするため、他の誰かが同じオブジェクトを使用してロックすることはほとんどないため、そのようなロックはほとんど役に立ちません。2番目のバリアントは、私にとってはるかに理にかなっています。

同時に、myClass 変数もこのメソッド内でしか知られていないため、他のスレッドがアクセスする可能性は低いため、おそらくここでロックはまったく必要ありません。詳細を説明するには、より完全な例が必要です。

于 2013-02-06T17:49:58.297 に答える
1

違いは、ロックのクラスとそのスコープです。どちらのトピックも、同期とほぼ直交しています。

  • クラスが異なるオブジェクトのサイズは異なる場合があります

  • 異なるスコープのオブジェクトは、異なるコンテキストで利用できる場合があります

基本的に、同期に関してはどちらも同じように動作します

于 2013-02-06T17:57:05.347 に答える
1

In general, you want to lock on the "root" object of the data you're manipulating. If you're, eg, going to subtract a value from a field in object A and add that value to object B, you need to lock some object that is somehow common (at least by convention) between A and B, possibly the "owner" object of the two. This is because you're doing the lock to maintain a "contract" of consistency between separate pieces of data -- the object locked must be common to and conceptually encompassing of the entire set of data that must be kept consistent.

The simple case, of course, is when you're modifying field A and field B in the same object, in which case locking that object is the obvious choice.

A little less obvious is when you're dealing with static data belonging to a single class. In that case you generally want to lock the class.

A separate "monitor" object -- created only to serve as a lockable entity -- is rarely needed in Java, but might apply to, say, elements of two parallel arrays, where you want to maintain consistency between element N of the two arrays. In that case, something like a 3rd array of monitor objects might be appropriate.

(Note that this is all just a "quick hack" at laying out some rules. There are many subtleties that one can run into, especially when attempting to allow the maximum of concurrent access to heavily-accessed data. But such cases are rare outside of high-performance computing.)

Whatever you choose, it's critical that the choice be consistent across all references to the protected data. You don't want to lock object A in one case and object B in another, when referencing/modifying the same data. (And PLEASE don't fall into the trap of thinking you can lock an arbitrary instance of Class A and that will somehow serve to lock another instance of Class A. That's a classical beginner's mistake.)

In your above example you'd generally want to lock the created object, assuming the consistency you're assuring is all internal to that object. But note that in this particular example, unless the constructor for MyClass somehow lets the object address "escape", there is no need to lock at all, since there is no way that another thread can get the address of the new object.

于 2013-02-06T18:08:11.773 に答える
0

どちらの例も、適切な同期方法ではありません。はプライベート フィールドとしてlock Object配置する必要があります。MyClass

于 2013-02-06T17:57:47.187 に答える