質問

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

  1. Mutexインスタンスの周りにWeakReferenceをラップする必要があるのはなぜですか? StringからMapを作成する方が良いとは思わない->ミューテックス?
  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;
        }
    }
    
役に立ちましたか?

解決

ループおよびブルーノコンデほぼカバーしていますが、そのコードを書いてから...

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

  

WeakReferenceをラップする必要がある理由   Mutexインスタンスの周辺?

マップは WeakHashMap です。 :

private final Map mutexMap = new WeakHashMap();

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

  

実装ノート:値オブジェクト   WeakHashMapで普通に保持されています   強い参照。したがって、注意が必要です   値オブジェクトがすることを保証するために取られた   独自のキーを強く参照しない、   直接的または間接的に   これにより、キーが   破棄されました。値オブジェクト   を介して間接的にキーを参照する場合があります   WeakHashMap自体;あれは   値オブジェクトは強く参照する場合があります   関連付けられている他のキーオブジェクト   値オブジェクトは、順番に、強く参照します   最初の値オブジェクトのキーに。   これに対処する1つの方法は、ラップすることです   内の値自体   挿入前のWeakReferences、として   in:m.put(key、new   WeakReference(value))、次に   各getでアンラップします。


  

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

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


  

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

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

  • WeakReference にはガベージコレクトされた(またはそもそもそこになかった)
  • WeakReferenceのコンテンツは、参照が取得された後にガベージコレクションされます

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

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


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

他のヒント

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

1-@Loopには良い答え

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

 Mutex mutex = ref.get();

この場合:

  • エントリが map
  • にまだ存在していない可能性があります
  • 存在する場合、 Mutex mutex = ref.get();
  • の実行前に収集される場合があります

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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top