У меня есть два потока, каждый из которых имеет свой счетчик: нить A имеет counterA, поток B имеет счетчик B. Каждый поток должен использовать оба счетчика: нить A должна использовать counterA и counterB, а также поток B должен использовать оба. Я использую AtomicInteger и делясь счетчиками между двумя потоками, которые я передаю им в качестве аргументов для потоков, и каждый поток хранит два счетчика в частных полях.безопасная публикация, аргумент, проходящий
// ...
AtomicInteger counterA = new AtomicInteger(0);
AtomicInteger counterB = new AtomicInteger(0);
Thread tA = new Thread(new RunnableA(counterA, counterB));
Thread tB = new Thread(new RunnableB(counterA, counterB));
// ... in the constructor of RunnableA ...
RunnableA(AtomicInteger counterA, AtomicInteger counterB) {
this.counterA = counterA;
this.counterB = counterB;
}
//...
// The same for RunnableB
Это safe publishing из двух счетчиков? Безопасная публикация необходима, поскольку ссылка на объект недостаточно безопасна для совместного использования объекта между потоками. Как я могу добиться безопасного опубликования в этом случае?
Заранее спасибо.
«Я не могу сразу увидеть, как это может быть» - если к счетчикам обращаются за пределами вновь созданных потоков как переменные экземпляра Runnables. Значения, инициализированные в конструкторе, не гарантируются, чтобы быть видимыми перед доступом, если, например, объявить хотя бы одну из переменных экземпляра окончательной, см. Https://shipilev.net/blog/2014/safe-public-construction/ –
Ну да ... но как можно получить эти переменные с помощью * ничего * до того, как конструктор вернется? Посмотрите на код для конструктора. (Я знаю, что означает безопасная публикация, а «final» - только один способ его достижения.) –
«Когда вызывается start(), между вызовом start() текущего потока и запуском нового потока происходит событие(). Это означает, что гарантируется безопасная публикация переменных для дочернего потока ». Это то, что я считаю полезным. Например, не нужно объявлять «переменные аргументов» (this.counterA, this.counterB) как окончательные в Runnable, даже если Runnable сконструирован в основном потоке, а затем эти переменные аргументов доступны в созданный поток. –