web-dev-qa-db-ja.com

JavaにスレッドセーフなMessageDigestが必要です

パフォーマンスが重要な環境でMessageDigestを使用して、複数のスレッドから複数のキーをハッシュする必要があります。 MessageDigestはその状態をオブジェクトに格納するため、スレッドセーフではないことを知りました。キーのスレッドセーフハッシュを実現する最良の方法は何でしょうか。

使用事例:

MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");

//somewhere later, just need to hash a key, nothing else
messageDigest.update(key);
byte[] bytes = messageDigest.digest(); 

具体的には:

  1. ThreadLocalの動作は保証されますか?パフォーマンスが低下しますか?
  2. GetInstanceによって返されるオブジェクトは異なり、それらは互いに干渉しませんか?ドキュメントには「新しい」オブジェクトと記載されていますが、それが(共有)共有具象クラスの単なるラッパーであるかどうかはわかりません。
  3. GetInstance()が「実際の」新しいオブジェクトを返す場合、ハッシュを計算する必要があるたびに新しいインスタンスを作成することをお勧めしますか?パフォーマンスのペナルティに関して-それはどれほどコストがかかりますか?

私の使用例は非常に単純です-単純なキーをハッシュするだけです。同期を使用する余裕はありません。

おかげで、

26
Anil Padia

必要になるたびにnew MessageDigestインスタンスを作成します。

getInstance()から返されるインスタンスはすべて異なります。別々のダイジェストを維持するため、これらは必要です(それでも不十分な場合は here's ソースへのリンク)。

ThreadLocalcanは、スレッドプールと共に使用すると、構築にコストがかかるオブジェクトを維持するためにパフォーマンス上の利点を提供します。 MessageDigestの構築はそれほど高価ではありません(ここでも、ソースを確認してください)。

41
parsifal

別の方法として、MessageDigest用のApache Commonsのスレッドセーフラッパーである DigestUtils を使用します。

sha1() は必要なことを行います:

byte[] bytes = sha1(key)

5
fishyfriend

DigestUtilsは、生のMessageDigestよりスレッドセーフではないようです。依然として内部ではMessageDigest.getInstanceを使用しています。

1
Big Kahuna