hashalgalgorithm . computehash()线程安全吗?



我不能得到一个明确的答案,所以这个问题。过去有几个SO帖子提到HashAlgorithm的实例不是线程安全的MSDN文档中的引用片段。

  • 为什么SHA1。ComputeHash在多线程的高负载下失败?
  • HMACSHA1.ComputeHash()线程安全问题
  • 哪段代码性能更好?

但是,当前的MSDN文档没有这样说。令人惊讶的是,下面的代码在net3.1和net5.0上没有爆炸,但是在net6.0上可以爆炸。所以,看起来它是线程安全的(也许),但也许net6.0有一个错误。

//<TargetFrameworks>net6.0;net5.0;netcoreapp3.1;net48</TargetFrameworks>
[Explicit]
[Test]
public void Bork_HashAlgorithm()
{
const int iterations = 1_000_000;
var bytes = Encoding.UTF8.GetBytes("the overtinkerer");
using (var md5 = MD5.Create())
{
Parallel.For(0, iterations, (i, loop) =>
{
md5.ComputeHash(bytes);
});
}
}

异常信息:

SafeHandle不能为空。(参数pHandle)

不,它不是线程安全的。

我们在峰值负载下看到相同的异常:SafeHandle cannot be null. (Parameter 'pHandle')和MD5提供商,SHA1和SHA256的类似错误,到处都是。

然而,我们发现使用"单例"仍然是有益的。用lock创建HashAlgorithm的实例,它仍然比每次创建一个单独的实例快3倍。

这是基准

md5re 1,282.5 ns 726.26 ns 39.81 ns 0.0801 0.0286 0.0038 > 512 B
MD5SingletonWithLock 402.2 ns 39.38 ns 2.16 ns 0.0610 384 B
MD5_HashData 467.7 ns 33.26 ns 1.82 ns 0.0548 344 B