Нужна потоковая безопасность 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();
В частности:
- Будет ли ThreadLocal гарантированно работать? Будет ли производительность
штраф?
- Являются ли объекты, возвращаемые getInstance разными, и они
не мешают друг другу? В документации указано "новое"
объект, но я не уверен, является ли это просто оболочкой (совместно используемой)
общий конкретный класс?
- Если getInstance() возвращает "реальные" новые объекты,
целесообразно создавать новый экземпляр каждый раз, когда мне нужно
рассчитать хэш? Что касается штрафа за производительность - насколько дорого
это?
Мой пример использования очень прост - просто хэш - простой ключ. Я не могу позволить использовать синхронизацию.
Спасибо,
Ответы
Ответ 1
Создайте новый экземпляр MessageDigest
каждый раз, когда вам это нужно.
Все экземпляры, возвращаемые из getInstance()
, различны. Они должны быть, поскольку они поддерживают отдельные дайджесты (и если этого недостаточно для вас, здесь ссылка на источник).
ThreadLocal
может обеспечить преимущество в производительности при использовании с threadpool, чтобы поддерживать дорогостоящие объекты. MessageDigest
не особенно дорого стоит (еще раз посмотрите на источник).
Ответ 2
В качестве альтернативы используйте DigestUtils, потокобезопасную оболочку Apache Commons для MessageDigest.
sha1() делает то, что вам нужно:
byte[] bytes = sha1(key)
Ответ 3
DigestUtils, похоже, уже не является потокобезопасным, чем raw MessageDigest. Все еще использует MessageDigest.getInstance под обложками.