需要Java中的线程安全MessageDigest

Ani*_*dia 25 java performance message-digest

我需要在性能关键环境中使用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(); 
Run Code Online (Sandbox Code Playgroud)

特别:

  1. ThreadLocal会保证有效吗?它会有性能损失吗?
  2. getInstance返回的对象是否不同,它们是否相互干扰?文档说"新"对象,但我不确定它是否只是(共享)共享具体类的包装器?
  3. 如果getInstance()返回"真正的"新对象,那么每次我需要计算哈希值时是否建议创建一个新实例?在性能损失方面 - 它的成本是多少?

我的用例非常简单 - 只需哈希一个简单的密钥.我不能使用同步.

谢谢,

par*_*fal 43

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

返回的所有实例getInstance()都是不同的.他们需要,因为他们维护单独的摘要(如果这对你不够,这里是链接到源).

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

  • @AnilPadia - 我强烈**推荐**不**使用`ThreadLocal`.这是过早的优化.我写了一个微基准测试,大约花了2*微*秒来创建一个新的`MessageDigest`.使用摘要的代码将远远超过*far*. (7认同)

fis*_*end 5

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

sha1()做你需要的:

byte[] bytes = sha1(key)

  • 请参阅下面的答案;DigestUtils 并不比 MessageDigest 更线程安全,因为 DigestUtils.getDigest() 只是调用 MessageDigest.getInstance() 并将已检查的异常转换为未检查的异常。 (2认同)
  • 这里的要点是MessageDigest不是线程安全的,因此在并发环境中重用相同的实例会导致不可预测的结果.每次解决您的问题时使用新的/不同的实例(例如通过调用MessageDigest.getInstance).DisgestUtils是线程安全的,意思是它的每个便捷方法都使用一个新的MessageDigest实例,每个实例都调用(在几次调用之后)MessageDigest.getInstance创建一个新实例.例如每次调用DigestUtils.sha256Hex("我的字符串"); 将使用MessageDigest的不同实例 (2认同)