41

我需要在性能关键的环境中使用 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() 返回“真实”新对象,是否建议每次需要计算哈希时都创建一个新实例?在性能损失方面 - 它的成本是多少?

我的用例非常简单——只需散列一个简单的键。我负担不起使用同步。

谢谢,

4

3 回答 3

61

MessageDigest每次需要时创建一个新实例。

从返回的所有实例getInstance()都是不同的。它们必须是,因为它们维护单独的摘要(如果这对您来说还不够,这里有一个源链接)。

ThreadLocal 与线程池一起使用时可以提供性能优势,以维护构建成本高的对象。MessageDigest构建起来并不是特别昂贵(再次查看源代码)。

于 2013-07-09T18:29:26.113 回答
6

作为替代方案,使用DigestUtils,Apache Commons 的 MessageDigest 线程安全包装器。

sha1()做你需要的:

byte[] bytes = sha1(key)

于 2014-12-18T23:31:03.413 回答
1

您可以使用我编写ImmutableMessageDigest的开源库Caesar 。

它本质上包装了一个实例并在每次或调用MessageDigest之前克隆它。digest()update()

于 2020-08-19T14:09:38.453 回答