Этот код из Java параллелизма на практике ThreadSafe?

1

Это может показаться глупым, но я не могу получить этот. VolatileCachedFactorizer хранит экземпляр OneValueCache и повторно инициализирует его при каждом вызове. Не должно ли это назначение выполняться в синхронизированном блоке?

    @Immutable
    class OneValueCache {
        private final BigInteger   lastNumber;
        private final BigInteger[] lastFactors;

        public OneValueCache(BigInteger i, BigInteger[] factors) {
            lastNumber = i;
            lastFactors = Arrays.copyOf(factors, factors.length);
        }

        public BigInteger[] getFactors(BigInteger i) {
            if (lastNumber == null || !lastNumber.equals(i))
                return null;
            else
                return Arrays.copyOf(lastFactors, lastFactors.length);
        }
    }

    public class VolatileCachedFactorizer implements Servlet {
        private volatile OneValueCache cache =
            new OneValueCache(null, null);
        public void service(ServletRequest req, ServletResponse resp) {
            BigInteger i = extractFromRequest(req);
            BigInteger[] factors = cache.getFactors(i);
            if (factors == null) {
                factors = factor(i);
                cache = new OneValueCache(i, factors); // is this line ok?
            }
            encodeIntoResponse(resp, factors);
        }
    }
  • 0
    больше похоже на пост обзора кода.
  • 0
    Это не для проверки кода, это код из Java Concurrency на практике. Я как-то запутался в этом.
Показать ещё 7 комментариев
Теги:
concurrency

1 ответ

1
Лучший ответ

Переменная cache volatile. Это означает, что происходит действие записи - до последующего действия чтения, которое наблюдает за письменным значением. Поэтому объект, о котором идет речь, был безопасно опубликован в другой поток, и дальнейшая синхронизация не требуется.

Обратите внимание, что поскольку OneValueCache является неизменным классом, даже без летучих ("публикация через гонку данных"), код по-прежнему будет потокобезопасным в том смысле, что поток, если он когда-либо наблюдает объект, будет гарантирован полностью соблюдайте его. Однако без volatile нет гарантии, что ссылка на объект никогда не будет наблюдаться другим потоком.

  • 0
    Поскольку построение OneValueCache не является атомарным, не может ли быть случай, когда два потока одновременно OneValueCache свой объект и какой из них назначается для ссылки на cache непредсказуемо?
  • 0
    @SunnyAgarwal Конечно нет. Каждый поток создает новый экземпляр кэша. И между этими двумя потоками нет статических переменных или других общих состояний.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню