SecureRandomスレッドは安全ですか?


103

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

回答:


108

はい、そうです。これはRandom事実上スレッドセーフな実装を常に備えていたを拡張し、Java 7以降、スレッドセーフを明示的に保証しています。

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


3
更新していただきありがとうございます。奇妙なことに、バグは「修正されない」としてクローズとマークされています。しかし、彼らはとにかくそれを修正しました。まあ、私は彼らのバグデータベースのサイズを羨ましくはありません。
Yishai、2011

4
aの初期化はSecureRandom遅くなるだけでなく、エントロピーがないためにハングする可能性があります
Walter Tross

8
ThreadLocalRandomは非常に簡単に解読できるため、生成された値を公開する場合は、代わりにSecureRandomを使用してください。jazzy.id.au
default/

2
ここで手足を出し、この答えが間違っていると言います。スレッドの安全性を保証するRandomのコントラクトは、サブクラスを拘束しません。確かに、ドキュメント化されたRandomの他のすべてのプロパティはサブクラスにバインドされていないため、スレッドセーフを想定する必要がある理由はわかりません。
James K. Polk大統領、

2
@JamesKPolkスーパータイプのプロパティを保持できないと、代入可能性の原則に違反します。
エリクソン2018年

11

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

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

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

    SecureRandom rnd = ...;

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

3
少なくともJDK 10では、SecureRandomはプロバイダーに基づいており、プロバイダーがスレッドセーフかどうかをチェックし、そうでない場合にのみ同期します。
nafg

java.security.SecureRandom#nextBytesJava 8では同期されません。同期したJavaのバージョンを指定してください#nextBytes
Jaime Hablutzel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.