изменчивый против окончательного. Какая польза от финала здесь

1

Ниже приведен фрагмент кода из параллелизма на практике.

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);  
}  
}


//Volatile is not enough to make VolatileCachedFactorizer thread safe? Why we need final   specifier in OneValueCache. 
public class VolatileCachedFactorizer implements Servlet {  
  private volatile OneValueCache cache = new OneValueCache(null, null); 
  //Servlet service method. 
  public void service(ServletRequest req, ServletResponse resp) {  
     BigInteger i = extractFromRequest(req);  
     BigInteger[] factors = cache.getFactors(i);
     //Check factors are null or not.  
     if (factors == null) {  
       factors = factor(i);  
       cache = new OneValueCache(i, factors);  
     }  
     encodeIntoResponse(resp, factors);  
  }  
} 

Каково использование объявления полей в качестве окончательного в OneValueCache. "volatile кеш OneValueCache" гарантирует, что объект будет видимым для всех других потоков, и я предполагаю, что записи до того, как волатильная запись будет видна для всех других потоков.

Теги:

3 ответа

4

Заключительные поля делают OneValueCache неизменяемым, тем самым делая его потокобезопасным. Они также имеют специальную семантику, определенную JLS, в частности, любой поток сможет увидеть правильно построенный объект с окончательными полями, инициализированными до его единственного правильного значения.

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

JCIP объясняет, что OneValueCache - это неизменный ссылочный класс, используемый для хранения двух битов данных. Это безопаснее, чем обновление двух полей в методе, поскольку оно не является атомарным. Затем OneValueCache становится volatile в сервлете, потому что его нужно изменить, но является атомарным назначением, поэтому синхронизация не требуется.

  • 0
    +1 для безопасности потока на финале, слишком много людей забывают об этом
  • 0
    Также бывает принято, что любое поле становится окончательным :)
Показать ещё 4 комментария
2

Это две разные вещи. В общем,

volatile → Создает барьер памяти, который принудительно очищает данные в кэше и заставляет данные считывать из основной памяти. Таким образом, все потоки всегда могут получать обновленные данные для этого конкретного поля.

final ->

  1. для примитивов → указывает, что значение не может измениться

  2. для не-примитивов → Ссылки не могут меняться (т.е. ссылка не может указывать на другой объект). Чтобы объект/поле было неизменным, вам необходимо убедиться, что он транзитно доступен конечными полями, и ссылка на него не исчезает.

PS: окончательная и неизменность - это две разные концепции. Итак, если вы слышали о неизменности, пожалуйста, поймите, что она отличается от окончательной.

0

Похоже, что класс OneValueCache должен быть неизменным, поэтому объявление окончательных значений гарантирует, что на каком-то более позднем этапе программист не пытается расширить класс и перезаписать значения.

Ещё вопросы

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