LINUX.ORG.RU

Java — private volatile fields without getters

 ,


0

4

В программе сложные вычисления выполняются в отдельном потоке:

public class MyThread extends Thread {

    private volatile boolean running = false;

    public void setRunning(boolean run) {
        running = run;
    }

    ...
}

Переменная (поле) running используется для управления выполнения потока (в методе run() ). Поле running имеет только сеттер (setRunning() ). Т.е., другие потоки не могут получать значение этой переменной / не зависят от неё. Сам метод setRunning() вызывается из основного потока и, соответственно, выполняется в основном потоке, а не в потоке MyThread. Поэтому возможен случай, когда потоки выполняются на разных ядрах процессора, и при выполнении метода setRunning() в основном потоке / на одном ядре, переменная running может(?) кэшироваться в кэш-памяти этого ядра процессора: http://tutorials.jenkov.com/java-concurrency/volatile.html. Хотя переменная running принадлежит потоку MyThread, ей незачем кэшироваться в кэш-памяти этого ядра, на котором выполняется основной поток. Тем временем, на другом ядре, поток MyThread может прочитать значение переменной running, которая не синхронизирована. Или такое не может произойти?

  • Так, нужно ли объявлять переменную running (которая private и без геттера) как volatile?

P. S. private volatile fields without getters -> частные Летучие поля без добытчиков  — © Google Translate :)


В вашем примере не нужно.

tyamur ★★
()

Переменная не принадлежит никакому потоку, переменная это просто ячейка памяти. private, классы и тд это всё шелуха. Без volatile компилятор может делать смелые предположения о переменной, то бишь он может считать, что она никогда не поменяется в другом потоке и кешировать её. С volatile он этих предположений делать не имеет права и всегда будет её проверять. Поэтому в данном случае надёжней использовать volatile. Хотя скорей всего и без него работать будет, JVM обычно не так агрессивно оптимизирует, как некоторые компиляторы.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)

spec:

An action that starts a thread synchronizes-with the first action in the thread it starts.
Т.е. всё, что было сделано в главном потоке до запуска нового, будет видно в новом. И если эта переменная ставится перед стартом нового потока и никогда не изменяется (лучше бы в конструктор её передавать тогда и объявить как final), то синхронизировать ничего не нужно.

P.S. Хотя если ТС имеет в виду, что setRunning будет вызываться во время выполнения дочернего потока, то volatile нужен, конечно.

xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 4)

Для того, что ты хочешь сделать, есть уже готовые Thread.interrupt и Thead.isInterrupted.

O02eg ★★★★★
()

Поле running для каждого экземпляра класса MyThread своё. Извне воздействовать на это поле можно вызовом метода setRunning(желаемое значение). Другие потоки кроме работающего потока этого же экземпляра не способны увидеть значение этого поля.

iZEN ★★★★★
()
Ответ на: комментарий от xaizek

xaizek:

Хотя если ТС имеет в виду, что setRunning будет вызываться во время выполнения дочернего потока, то volatile нужен, конечно.

Ну да, setRunning() вызывается во время выполнения дочернего потока — при создании:

myThread = new MyThread();
myThread.setRunning(true);
myThread.start();
и при завершении программы:
myThread.setRunning(false);
И вообще, эта программа для Android. Thread.stop, Thread.suspend and Thread.resume не рекомендуются использовать, поэтому для приостановки потока использую ещё одну такую переменную — paused.

Mg_usr
() автор топика
Ответ на: комментарий от Mg_usr

Чувак, кури JLS, раздел 17.4 — там про соотношение happens—before и про volatile в частности всё написано.

Правда, Android в общем случае болт клал на Java Memory Model и её гарантии. Что-то более-менее работающее они смогли сделать только в Android 4.3, а Java TCK (technology compatibility kit) для Android отсутствует как класс.

P.S. На тему многопоточного программирования в Java есть классическая книга “Java Concurrency in Practice”. Прочти её — и все подобные вопросы отпадут раз и навсегда.

Bass ★★★★★
()
Последнее исправление: Bass (всего исправлений: 1)

в вашем примере надо использовать AtomicBoolean и не парить мозг реализациями. А ответ на ваш конкретный вопрос - см. реализация этого самого AtomicBoolean. Вообще, надо меньше спрашивать на форумах, а смотреть реализации стандартный вещей - 90% вопросов отпадут.

vtVitus ★★★★★
()
Последнее исправление: vtVitus (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.