Безопасен ли доступ к циклу bool из другого потока? - PullRequest
0 голосов
/ 23 июня 2018

Я пишу некоторый код Java и у меня есть надуманный пример, и я не совсем уверен, является ли это потокобезопасным кодом.

По сути, у меня есть цикл while, который проверяет bool, и я хочу установить это bool false из другого потока.

Обратите внимание на следующее

    public void start() {
    mRunning = true;

    thread = new Thread()
    {
        public void run()
        {
            while (mRunning) {

            }
        }
    }
    thread.start();
}

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

public void stop() {
    mRunning = false;
}

Может ли этот код привести к нежелательному поведению? Если это так, я должен просто сделать это?

public void stop() {
    sychronized(this) {
        mRunning = false;
    }
}

Ответы [ 2 ]

0 голосов
/ 23 июня 2018

Если вам нужна только связь между потоками, а не взаимное исключение , используйте переменную volatile:

private static volatile boolean mRunning = false;

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

Должен ли я просто сделать это?

public void stop() {
    synchronized (this) {
        mRunning = false;
    }
}

Вы можете, но не должны!В любом случае, вы получите неожиданное поведение (этот ответ объясняет почему).

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

0 голосов
/ 23 июня 2018

Может ли этот код привести к нежелательному поведению?

Может.
Поток в stop() сможет установить false значение общего boolean mRunning field.
Но поток в start() может не увидеть изменения, если это поле не объявлено как volatile, так как поток, выполняющий start(), не принимает монитор текущего объекта и поэтому потокСостояние памяти может отличаться от основного состояния памяти.

Так что start() может продолжать цикл в операторе while.

Таким образом, вы должны убедиться, что общий флаг объявлен как volatile boolean mRunning.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...