Безопасно ли защищать поток SecureRandom?

Является SecureRandom поток безопасно? То есть, после его инициализации можно ли рассчитывать на доступ к следующему случайному числу, чтобы обеспечить безопасность потока? Изучение исходного кода, кажется, показывает, что это так, и этот отчет об ошибке, кажется, указывает на то, что отсутствие документации в качестве поточно-ориентированной является проблемой javadoc. Кто-нибудь подтвердил, что это на самом деле потокобезопасно?

4 ответа

Решение

Да, это. Расширяется Random, которая всегда имела де-факто реализацию потоковой безопасности, и, начиная с Java 7, явно гарантирует безопасность потоков.

Если много потоков используют один SecureRandom, может быть раздор, который вредит производительности. С другой стороны, инициализация SecureRandom экземпляр может быть относительно медленным. Будет ли лучше разделить глобальный ГСЧ или создать новый для каждого потока, будет зависеть от вашего приложения. ThreadLocalRandom класс может быть использован в качестве шаблона, чтобы обеспечить решение, которое поддерживает SecureRandom,

Текущая реализация SecureRandom является потокобезопасным, в частности, два метода мутации nextBytes(bytes[]) а также setSeed(byte[]) синхронизированы.

Ну, насколько я могу судить, все методы мутации в конечном итоге направляются через эти два метода, и SecureRandom переопределяет несколько методов в Random чтобы обеспечить это. Что работает, но может быть хрупким, если реализация будет изменена в будущем.

Лучшее решение - вручную синхронизировать на SecureRandom экземпляр первый. Это означает, что каждый стек вызовов получает две блокировки для одного и того же объекта, но это обычно очень дешево на современных JVM. То есть нет особого вреда в явной синхронизации себя. Например:

    SecureRandom rnd = ...;

    byte[] b = new byte[NRANDOM_BYTES];
    synchronized (rnd) {
        rnd.nextBytes(b);
    }

См. https://bugs.openjdk.java.net/browse/JDK-8165115 , который был исправлен в Java 9.

В нем говорится:

объекты безопасны для использования несколькими параллельными потоками. Поставщик услуг может объявить, что он является потокобезопасным, установив для атрибута поставщика услуг "ThreadSafe" значение "true" при регистрации поставщика. В противном случае SecureRandomclass будет синхронизировать доступ к следующим SecureRandomSpiметоды: SecureRandomSpi.engineSetSeed(byte[]), SecureRandomSpi.engineNextBytes(byte[]), SecureRandomSpi.engineNextBytes(byte[], SecureRandomParameters), SecureRandomSpi.engineGenerateSeed(int), а также SecureRandomSpi.engineReseed(SecureRandomParameters).

Да. Это абсолютно потокобезопасно. На самом деле, я бы пожаловался, что замок слишком агрессивен. Целый engineNextBytes() синхронизирован.

Если честно, я бы не знал, небезопасно ли это. Проблема с потоками, вероятно, вносит больше случайности:)

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