это считается как экранированный и не потокобезопасным - PullRequest
3 голосов
/ 15 апреля 2020

после прочтения «java параллелизма на практике» в пункте 3.4 говорится:

"
Объект является неизменным, если:
• Его состояние не может быть изменено после построения; и.
• Все его поля являются окончательными, и.
• Он правильно построен (, эта ссылка не скрывается во время построения ).
"

А теперь я есть класс:

class A {
  private final static ConcurrentMap<String, A> cache = new ConcurrentHashMap<>();
  private final code;
  private final name;

  A(String code, String name) {
    this.code = code;
    this.name = name;
    cache.put(code, this); // does this escaped? and make immutable A not thread safe anymore?
  }

 public static A getA(String code) {
    return cache.get(code);
 }

}

, и приведенная ниже ссылка кажется полезной, но я все еще в замешательстве.
ссылка: Самостоятельная ссылка в конструкторе считается "экранирующей"?

summary: в вышеприведенном случае в конструкторе экранируется "this"? и является ли неизменяемый экземпляр все еще поточно-ориентированным?

более того, если я переместу переменную кэша в другой класс, что произойдет?

1 Ответ

0 голосов
/ 04 мая 2020

Технически, ссылка this действительно экранирует конструктор, так как он передается в кэш до возврата конструктора. То есть кэш получает ссылку на экземпляр A, который еще не полностью инициализирован. Любой, кто обращается к этому экземпляру одновременно через этот кеш, сможет наблюдать этот экземпляр, который еще не полностью инициализирован. Поскольку cache.put является последней строкой в ​​конструкторе, это, вероятно, не имеет значения на практике. Но лучше не рассчитывать на это, и оно сломается, как только A будет подклассом .

...