2

このブログ投稿は、文字列IDイディオムごとにミューテックスを実装する方法を示しています。使用される文字列IDは、HttpSessionIDを表すためのものです。

  1. なぜMutexインスタンスの周りにWeakReferenceをラップする必要があるのですか?文字列->ミューテックスからマップを作成する方が良いのではないですか?
  2. putを2回呼び出す必要があるのはなぜですか?

    public Mutex getMutex( String id )
    {                                  
        Mutex key = new MutexImpl( id );
        synchronized( mutexMap )
        {
            WeakReference<Mutex> ref = mutexMap.get( key );
            if( ref == null )
            {
                mutexMap.put( key, new WeakReference<Mutex>( key ) );
                return key;
            }
            Mutex mutex = ref.get();
            if( mutex == null )
            {
                mutexMap.put( key, new WeakReference<Mutex>( key ) );
                return key;
            }
            return mutex;
        }
    }
    
4

4 に答える 4

4

WeakHashMapの値オブジェクトは、通常の強力な参照によって保持されます。したがって、値オブジェクトが直接または間接的に自身のキーを強く参照しないように注意する必要があります。これにより、キーが破棄されるのを防ぐことができます。値オブジェクトは、WeakHashMap自体を介してそのキーを間接的に参照する場合があることに注意してください。つまり、値オブジェクトは、関連する値オブジェクトが最初の値オブジェクトのキーを強く参照する他のキーオブジェクトを強く参照する場合があります。これに対処する1つの方法は、m.put(key、new WeakReference(value))のように、挿入する前に値自体をWeakReferences内でラップし、各getでアンラップすることです。

于 2009-05-05T09:09:18.743 に答える
2

1-@Loopには良い答えがあります。

2-エントリがWeakReferencesでラップされていると仮定すると、実行が行に到達する前に収集される可能性がputあるため、2番目が必要です。WeakReference

 Mutex mutex = ref.get();

この場合:

  • エントリがまだ存在していない可能性がありますmap
  • 存在する場合は、実行前に収集される場合があります。Mutex mutex = ref.get();
于 2009-05-05T09:12:32.263 に答える
1

'はWeakReference、httpセッションIDを参照する必要があるためにのみ使用されます。セッションが終了したという通知を受け取ることを常に100%確信できるとは限らないため、マップが拡大し続けることになります。

初めてputを呼び出すのは、マップにキーが含まれていないためです。2回目は、マップにキーが含まれていましたが、参照が存在しなくなったためです。

于 2009-05-05T09:10:20.193 に答える
1

LoopBrunoCondeはそれをほぼカバーしていますが、私がそのコードを書いたので...

設計の目標は、ユーザーがリリースメカニズムを呼び出さないようにすることでした。つまり、ユーザーがミューテックスを参照しなくなったときに、そのミューテックスはガベージコレクションの対象になります。

なぜMutexインスタンスの周りにWeakReferenceをラップする必要があるのですか?

マップはWeakHashMapです:

private final Map mutexMap = new WeakHashMap();

このマップは、ミューテックスへの参照を保持するために使用されますが、キーと値に同じオブジェクトを使用する場合、そのオブジェクトはガベージコレクションの対象にはなりません。Javadoc:

実装上の注意:WeakHashMapの値オブジェクトは、通常の強力な参照によって保持されます。したがって、値オブジェクトが直接または間接的に自身のキーを強く参照しないように注意する必要があります。これにより、キーが破棄されるのを防ぐことができます。値オブジェクトは、WeakHashMap自体を介してそのキーを間接的に参照する場合があることに注意してください。つまり、値オブジェクトは、関連する値オブジェクトが最初の値オブジェクトのキーを強く参照する他のキーオブジェクトを強く参照する場合があります。これに対処する1つの方法は、m.put(key、new WeakReference(value))のように、挿入する前に値自体をWeakReferences内でラップし、各getでアンラップすることです。


文字列->ミューテックスからマップを作成する方が良いのではないですか?

その文字列値はいつガベージコレクションされますか?毎回同じ参照が渡されていますか?intern()が呼び出されましたか?インターンに電話した場合、ストリングはどのくらいの期間存続しますか?文字列がキーである場合、そのミューテックスへの参照を保持する必要がなくなった後、ミューテックスはガベージコレクションの対象とならない可能性があります。


putを2回呼び出す必要があるのはなぜですか?

メソッドがマップ内のミューテックスへの強力な参照を取得できるようになるまで、処理する2つのケースがあります。

  • WeakReferenceはガベージコレクションされています(またはそもそもそこにありませんでした)
  • WeakReferenceの内容は、参照が取得された後に収集されたガベージです。

putは一度だけ呼び出されます。メソッドは直後に戻ります。

(WeakReferenceは2番目の場所で再利用できますが、大幅な改善になるとは思いません。)


もちろん、誰かがコードに誤りを見つけた場合は、私に知らせてください。喜んで修正します。また、単体テストは実装がリークしていないことを確認しようとするため、コードを自由に変更して、テストを実行するとどうなるかを確認してください。

于 2009-05-05T09:31:39.533 に答える