Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > Java > Общие вопросы по Java, Java SE, Kotlin
Регистрация

Восстановить пароль
Повторная активизация e-mail

Ответ
 
Опции темы
Старый 08.03.2018, 21:55   #1
datgen
Пользователь
 
Регистрация: 30.03.2011
Сообщений: 35
Репутация: 10
По умолчанию разобраться с volatile

Добрый вечер.
Нашел такой пример и в нем действительно без volatile потоки не останавливаются

Код:

public class VolatileDemo {
    // вначале попробуйте без volatile
     volatile private boolean btExit = false;
     volatile private boolean isRunning = true;

    // задача для интерфейсного потока
    Runnable gui = new Runnable() {

        @Override
        public void run() {
            int k=-1;
            while (isRunning) {
                try {
                    k = System.in.read() ;
                    btExit = k>=0;
                    System.out.println("gui input: "+k);
                } catch (Exception e) {
                }
            }
            System.out.println("gui thread finished");
        }
    };

    // задача для игрового потока
    Runnable game = new Runnable() {

        @Override
        public void run() {
            int k=1;
            while (!btExit) {
                k+=k;
                k%=100;
                // System.out.print("");
            }
            isRunning=false;
            System.out.println("game thread finished");
        }
    };

    // запуск потоков
    public void start() {
        new Thread(gui).start();
        new Thread(game).start();
    }


    // чтобы остановить программу запущенную без volatile и без System.out.print(""); в игровом цикле
    // в Eclipse в окне консоли кликните на красный квадрат
    public static void main(String[] args) {
        new VolatileDemo().start();
    }
}

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

class Task2{

    private boolean b = false;

    Runnable runnable1 = new Runnable() {
        @Override
        public void run() {
            while (!b) {
                try {
                    System.out.println("+");
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    Runnable runnable2 = new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(500);
                b = true;
            } catch (InterruptedException e) {
            }
        }
    };

    public void start() {
        new Thread(runnable1).start();
        new Thread(runnable2).start();
    }
}

datgen вне форума   Ответить с цитированием
Старый 08.03.2018, 22:04   #2
p51x
Профессионал
 
Регистрация: 15.02.2010
Сообщений: 11,306
Репутация: 1868

icq: 216409213
По умолчанию

Потому что тут есть запись и компилятор это заметил, и не стал кэшировать.
__________________
Запомните раз и навсегда: помочь != "решите за меня"!
p51x на форуме   Ответить с цитированием
Старый 08.03.2018, 22:04   #3
alexzk
Участник клуба
 
Регистрация: 12.04.2017
Сообщений: 881
Репутация: 172
По умолчанию

Thread.sleep(500);

скорее всего, но все равно там ничего не гарантиравано без volatile. Что-то измените и все сломается.
Кросс-потоковое общение должно быть обязательно синхронизировано неким способом (там их несколько), в яве 1 из них volatile.

Вообще, отстутствие явной верной сихронизации м-у потоками так и проявляется - случайно что-то не так. Например, на 1 процессоре все ок, на 4 процессорах - все сломалось не понять как. Т.е. как только полезло "не понять что", начинаем проверять все между-поточные передачи данных и делать их верно синхронными.

Последний раз редактировалось alexzk; 08.03.2018 в 22:09.
alexzk вне форума   Ответить с цитированием
Старый 08.03.2018, 22:12   #4
datgen
Пользователь
 
Регистрация: 30.03.2011
Сообщений: 35
Репутация: 10
По умолчанию

Цитата:
Сообщение от p51x Посмотреть сообщение
Потому что тут есть запись и компилятор это заметил, и не стал кэшировать.
можно тут чуть подробнее пожалуйста
datgen вне форума   Ответить с цитированием
Старый 09.03.2018, 00:31   #5
Пепел Феникса
Модератор
Заслуженный модератор
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Адрес: Москва
Сообщений: 21,006
Репутация: 3402

icq: 446843180
skype: phoenix_proger
По умолчанию

Цитата:
Кросс-потоковое общение должно быть обязательно синхронизировано неким способом (там их несколько), в яве 1 из них volatile.
я бы не назвал volatile синхронизацией.
volatile говорит компилятору что значение может изменится в ином потоке, он отключает кеширование результата обращения.
__________________
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума   Ответить с цитированием
Старый 09.03.2018, 02:29   #6
alexzk
Участник клуба
 
Регистрация: 12.04.2017
Сообщений: 881
Репутация: 172
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
я бы не назвал volatile синхронизацией.
volatile говорит компилятору что значение может изменится в ином потоке, он отключает кеширование результата обращения.
Это скорее вы про С++ говорите
http://alenacpp.blogspot.com/2006/04/volatile.html
где ничего как раз не гарантируется - т.е. просто не оптимизируем и все.

А вот в яве
https://ru.stackoverflow.com/questio...le-%D0%B2-java

это уже атомарная операция.

Но лично я всегда делал так:

private final AtomicBoolean isSome = new AtomicBoolean(false);
alexzk вне форума   Ответить с цитированием
Старый 09.03.2018, 03:32   #7
Пепел Феникса
Модератор
Заслуженный модератор
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Адрес: Москва
Сообщений: 21,006
Репутация: 3402

icq: 446843180
skype: phoenix_proger
По умолчанию

главное это пункт 2 ответа, а не 1.

без этого модификатора, компилятор/JIT может оптимизировать чтение, это и в Java мире так же.
атомарность уже отличается, да(в С++ не гарантируется к примеру)
__________________
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.

Последний раз редактировалось Пепел Феникса; 09.03.2018 в 03:35.
Пепел Феникса вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
volatile 220Volt Общие вопросы C/C++ 8 08.02.2013 08:44
Объясните разницу модификаторов CONST и VOLATILE svatorus Помощь студентам 0 07.06.2012 13:13
Разобраться Nempak Общие вопросы C/C++ 2 27.03.2011 14:06
Interlocked-функции и volatile. Необходимость совместного использования. neokoder Win Api 0 21.03.2011 23:06


09:39.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru