0

ロック オブジェクトを非公開にするとロックがカプセル化され、クライアント コードがロックを取得できないのはなぜですか?

オブジェクトの組み込みロック

   public class A{
        private final Set<Integer> set = new HashSet<Integer>();

        public synchronized void addInt(int i){
            set.add(i);
        }
   }

プライベートロック

   public class B{
        private final Set<Integer> set = new HashSet<Integer>();

        public void addInt(int i){
             synchronized(set){
                  set.add(i);
             }
        }
   }
4

3 に答える 3

3

ええと、setそれはプライベートなので、別のクラスはまったくアクセスできません。その参照にアクセスできないために他の人が実行できない多くのことの 1 つに、同期が挙げられます。

ゲッターがその参照を (オブジェクトをラップまたはコピーせずに) 直接返す場合、他の誰かがそれを同期することができ、プライベート オブジェクトのロックの利点が無効になります。

于 2012-08-19T17:08:43.337 に答える
1

あなたが提供した両方の例では、組み込みモニターが使用されています。ただし、2 番目の例では、フィールドの固有のロックを使用していsetます。このプラクティスを使用するときは注意してください。 への参照を公開するとset、クラス外のコードがそのモニターで同期され、デッドロックが発生する可能性があります。

あなたが得ている違いは、 APIsynchronizedの使用との違いだと思います。java.util.concurrent.Lock得られるもののほとんどは、追加された柔軟性です ( Lockドキュメントから):

同期されたメソッドまたはステートメントを使用すると、すべてのオブジェクトに関連付けられた暗黙的な監視ロックへのアクセスが提供されますが、すべてのロックの取得と解放がブロック構造の方法で強制的に行われます。複数のロックが取得された場合は、逆の順序で解放する必要があります。すべてのロックは、ロックが取得されたのと同じレキシカル スコープで解放する必要があります。

同期されたメソッドとステートメントのスコープ メカニズムにより、監視ロックを使用したプログラミングがはるかに簡単になり、ロックに関連する多くの一般的なプログラミング エラーを回避するのに役立ちますが、より柔軟な方法でロックを操作する必要がある場合があります。たとえば、同時にアクセスされるデータ構造をトラバースするための一部のアルゴリズムでは、「hand-over-hand」または「チェーン ロック」を使用する必要があります。ノード A のロックを取得し、次にノード B を取得し、次に A を解放し、C を取得してから B を解放します。 Dなどを取得します。Lock インターフェイスの実装では、さまざまなスコープでロックを取得および解放したり、複数のロックを任意の順序で取得および解放したりできるため、このような手法を使用できます。

Lock API を使用してロックを取得する方法をさらに提供する 2 つのメソッド呼び出しもあります。

  • lockInterruptibly: スレッドが中断されない限り、ロックを取得します。
  • tryLock: 呼び出し時に解放されている場合にのみロックを取得します (オプションのタイムアウト)。

Java での並行性の標準的な参照は、「Java Concurrency in Practice」です。

于 2012-08-19T16:51:31.007 に答える
0

ロック オブジェクトを非公開にするとロックがカプセル化され、クライアント コードがロックを取得できないのはなぜですか?

正直なところ、この質問の意味がわかりません。
コード スニペットの違いは、使用されるロックです。最初のケースでは、メソッド全体Aが (の固有のロックを使用して) 同期されますが、2 番目のケースでは、変更しようとしているコレクションをロックします。つまり、2 つのスレッドが同時にメソッドに入ることができますが、1 つのスレッドは のロックを取得しようとしてブロックされますadd
この方法には 2 つの利点があります。1)ロックの粒度を定義します(短時間だけロックが必要な長いメソッドの場合、メソッド呼び出しの全期間にわたってロックするとパフォーマンスが低下します)。コレクションをスレッドセーフにします。
任意のオブジェクトをロックとして使用できることに注意してください。Object lock = new Object();
synchronized(lock){
//do something
}

于 2012-08-19T19:36:39.663 に答える