2015-09-11 2 views
2

У нас есть эти объекты:Java Параллелизм на практике: Листинг 3.12 и 3.13

// Листинг 3,12

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

// Листинг 3.13

@ThreadSafe 
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); 
     } 
     encodeIntoResponse(resp, factors); 
    } 
} 

В книге говорится, что VolatileCachedFactorizer - это сохранение потока. Зачем?

Например:

  1. Поток А считывает cache.getFactors (я);
  2. Затем поток B считывает cache.getFactors (i);
  3. Затем поток B пишет кеш.
  4. Затем поток A пишет кеш.

Можно ли считать этот поток нитью? Что я не понимаю?

ответ

3

Короткий ответ:

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

Более длинный ответ:

Итак, что желаемое поведение здесь? Это только то, что правильный ответ всегда задан, или же он также всегда реализуется ровно один раз, если два потока требуют его в строке?

Если это последний —, то есть, если вы действительно хотите сохранить каждый бит CPU —, тогда вы правы, это не потокобезопасно. В одно и то же время (или достаточно близко к нему) могли появляться два запроса, чтобы получить коэффициенты для одного и того же числа N, и если бы сроки были отработаны, оба потока могли бы вычислить это число.

Но с одноценным кешем у вас уже есть проблема пересчета вещей, которые вы уже знали. Например, что, если три запроса входят, для N, K и N снова? Запрос на K приведет к аннулированию кеша в N, и вам придется пересчитать его.

Таким образом, этот кеш действительно оптимизирован для «полос» одинакового значения, и поэтому стоимость двойного вычисления первой пары (или даже нескольких!) Ответов в этой полосе может быть приемлемой стоимостью: взамен , вы получаете код, свободный от блокировки и довольно простой для понимания.

Важно, что он никогда не дает вам неправильный ответ. То есть, если вы попросите N и K одновременно, ответ на K никогда не должен давать вам ответ за N. Эта реализация получает вам эту гарантию, поэтому я бы назвал ее потокобезопасной.

Смежные вопросы