web-dev-qa-db-ja.com

SecureRandomスレッドセーフですか?

SecureRandomスレッドセーフですか?つまり、初期化した後、次の乱数にアクセスしてスレッドセーフにすることができますか?ソースコードを調べると、それが示されているようです。 このバグレポート は、スレッドセーフとしてのドキュメントの欠如がjavadocの問題であることを示しているようです。誰もが実際にスレッドセーフであることを確認していますか?

95
Yishai

はい、そうです。それはRandomを拡張します。 デファクト スレッドセーフな実装、および Java 7、スレッドセーフを明示的に保証

多くのスレッドが単一のSecureRandomを使用している場合、パフォーマンスを損なう競合が存在する可能性があります。一方、SecureRandomインスタンスの初期化は比較的遅くなります。グローバルRNGを共有するのが最適か、スレッドごとに新しいRNGを作成するのが最適かは、アプリケーションによって異なります。 ThreadLocalRandom クラスをパターンとして使用して、SecureRandomをサポートするソリューションを提供できます。

98
erickson

SecureRandomの現在の実装はスレッドセーフです。具体的には、2つの変更メソッドnextBytes(bytes[])setSeed(byte[])が同期されます。

さて、私が知る限り、すべての変更メソッドは最終的にこれら2つのメソッドを経由し、SecureRandomRandomのいくつかのメソッドをオーバーライドしてそれを保証します。これは機能しますが、将来実装が変更されると脆弱になる可能性があります。

最善の解決策は、最初にSecureRandomインスタンスで手動で同期することです。これは、各コールスタックが同じオブジェクトで2つのロックを取得することを意味しますが、通常、最新のJVMでは非常に安価です。つまり、明示的に自分自身を同期してもそれほど害はありません。例えば:

    SecureRandom rnd = ...;

    byte[] b = new byte[NRANDOM_BYTES];
    synchronized (rnd) {
        rnd.nextBytes(b);
    }
11
Matt Quail