Нужен потокобезопасный MessageDigest в Java

Мне нужно хэшировать несколько ключей из нескольких потоков, используя 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() возвращает "реальные" новые объекты, целесообразно ли создавать новый экземпляр каждый раз, когда мне нужно вычислить хэш? С точки зрения снижения производительности - насколько это дорого?

Мой вариант использования очень прост - просто хешируйте простой ключ. Я не могу позволить себе использовать синхронизацию.

Спасибо,

3 ответа

Решение

Создать новыйMessageDigest экземпляр каждый раз, когда вам нужен.

Все экземпляры вернулись из getInstance() различны. Они должны быть, так как они поддерживают отдельные дайджесты (и если этого вам недостаточно, вот ссылка на источник).

ThreadLocal может обеспечить выигрыш в производительности при использовании с пулом потоков для поддержки дорогостоящих объектов. MessageDigest не особенно дорого построить (опять же, посмотрите на источник).

В качестве альтернативы используйте DigestUtils, поточно- ориентированную оболочку Apache Commons для MessageDigest.

sha1 () делает то, что вам нужно:

byte[] bytes = sha1(key)

Вы могли бы использовать ImmutableMessageDigest из Caesar, библиотеки с открытым исходным кодом, которую я написал.

По сути, он обертывает MessageDigest экземпляр и клонирует его перед каждым digest() или update() вызов.

DigestUtils, похоже, не более безопасен для потоков, чем необработанный MessageDigest. По-прежнему использует MessageDigest.getInstance под обложками.

Другие вопросы по тегам