Этот потокобезопасный?

Я хочу сделать мой класс поточно-безопасным без больших накладных расходов. Экземпляры будут редко использоваться одновременно, но это может произойти. Большая часть класса неизменна, в качестве кэша используется только один изменяемый член:

private volatile SoftReference<Map<String, Something>> cache
    = new SoftReference(null);

который присваивается в конструкторе (не разделяется), как

Map<String, Something> tmp = new HashMap<String, Something>();
tmp.put("a", new Something("a");
tmp.put("b", new Something("b");
cache = new SoftReference(tmp);

После назначения карта никогда не изменяется.

Это не проблема, когда два потока вычисляют кэш параллельно, так как значение будет одинаковым. Дополнительные накладные расходы на слово, сделанное дважды, являются приемлемыми.

Когда поток не увидит значение, вычисленное другим протектором, он вычислит его излишне, и это приемлемо. Этого не произойдет из-за изменчивости. Когда поток видит значение, вычисленное другим протектором, это нормально.

Единственная возможная проблема - поток, видящий несогласованное состояние (например, частично заполненную карту). Может ли это случиться?

Заметки:

  1. Я действительно хочу, чтобы на всю карту мягко ссылались, здесь нет смысла для карты, использующей софт-клавиши или значения.

  2. Я знаю о ConcurrentHashMap и, возможно, буду его использовать в любом случае, но мне любопытно, работает ли volatile только.

2 ответа

Решение

Единственная возможная проблема - поток, видящий несогласованное состояние (например, частично заполненную карту). Может ли это случиться?

Нет. Действия, выполняемые в потоке, должны выполняться так, как если бы они выполнялись по порядку. Запись изменчивой переменной происходит до любого чтения этого значения. Следовательно, инициализация карты происходит до того, как какой-либо поток прочитает ссылку на карту из поля.

Проблема с использованием мягкой ссылки в том, что вы можете потерять всю карту / кеш после GC. Это означает, что производительность вашего приложения может сильно пострадать. Вам лучше использовать кеш с политикой выселения, чтобы у вас никогда не возникало этой проблемы.

Летучие вещества здесь не делают никаких операций безопасными.

Вы не показали весь свой код, возможно, мы могли бы предложить несколько советов о том, как вы могли бы улучшить свой код, например, ваш пример кода должен компилироваться;)

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