Java 的 SHA-256 等哈希算法的哪些实现是线程安全的?

问题描述 投票:0回答:1

我需要在 Java 应用程序中计算 SHA-256 哈希值。 Apache HmacUtils 似乎适合于此。然而,在文档中它说“这个类是不可变的和线程安全的。但是Mac可能不是”。这里“Mac”指的是返回的实例,它实际上计算哈希值。

现在,我希望能够从多个线程计算哈希值,理想情况下它们不会互相阻塞。 实现这一目标的最佳方法是什么? 是否有参考哪种算法实际上是线程安全的? 我知道它还需要是可重入? 我应该为每个线程创建一个“Mac”实例以避免线程安全问题吗? (这样够吗?这样贵很多吗?)

java multithreading cryptography sha256 cryptographic-hash-function
1个回答
0
投票

有几种方法可以设置这些东西:

您为您拥有的每项工作创建一个线程。

换句话说,您创建一个新的

java.lang.Thread
实例(或
extends Thread
的类的实例),如果您运行它,它会执行一项工作,然后结束。

这是一个坏主意 - 至少,如果速度很重要并且您有大量工作要做。制作这些线程的实际成本取决于大量因素,真正的组合爆炸:JVM 版本、供应商、底层操作系统、底层架构。从速度角度来看,这可能是一个很好的方法,但是在某些组合中,这比替代方案慢得多,替代方案是拥有一组有限的线程(大约等于 CPU 中的核心数量,也许大约是 2 倍,但是与核心数量线性相关),并且这些线程将作业从 em 的中央队列中拉出,直到所有作业完成。

有各种框架可以让这个变得“好”(例如 fork/join、ExecutorPool 等),如果您想以某种方式处理所有这些,您可以在

java.util.concurrent

 中使用集合类型作为“所有作业的中央队列”要做的就是所有线程都从'.
拉出

重点是,担心为每个作业创建 Mac 对象的新实例所涉及的成本(实际上,为了避免任何线程安全问题,您最终必须要做的事情)有点像如果你没有解决房间里的大象问题,那就太愚蠢了。换句话说,

如果这描述了您当前的设置,请先修复它,这样您最终会:

你有工作,还有一群执行者来完成工作。

...并且执行器的数量是有限的(与机器中CPU核心的数量相同的数量级)。

然后,相对于作业计数,您拥有的线程数量是恒定的,即可以忽略。

解决方案就是简单地为每个线程创建 1 个 Mac 对象。这意味着每个 CPU 有 1 个 mac 对象,这是微不足道的、可以忽略的成本。尝试使用更少的 mac 对象是没有意义的;即使这本来就很好(即 mac 对象根本没有上下文,这显然不是真的),你也无法获得可测量的性能,或者如果不知何故这些 mac 对象

线程安全但确实有状态(因为 JVM 非常擅长消除不相关的同步成本,因为该对象永远不会从多个线程中使用,即使如果这样做的话它会成功)。

实现这一目标的一个简单工具就是拥有一个

ThreadLocal

:

private static final ThreadLocal<Mac> MACS = new ThreadLocal<Mac>() { @Override public Mac initialValue() { return HmacUtils.getInitializedMac("algorithm", key); } }; public void codeThatIsRunInManyThreads() { Mac mac = MACS.get(); mac.reset(); // use mac here. Rest safely knowing it's all safe now. }
    
© www.soinside.com 2019 - 2024. All rights reserved.