Russian Qt Forum
Ноябрь 25, 2024, 01:12 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Таймер в потоке  (Прочитано 12991 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #15 : Сентябрь 08, 2018, 12:27 »

Интересно, с какими типами переменных такие операции атомарны?
В данном случае атомарность ни при чем, одна нитка пишет только true, другая - только false, причем писать одновременно они не могут. "Так защищаться можно"  Улыбающийся
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #16 : Сентябрь 08, 2018, 12:50 »

Интересно, с какими типами переменных такие операции атомарны?

Очень интересно
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #17 : Сентябрь 08, 2018, 13:14 »

В данном случае атомарность ни при чем, одна нитка пишет только true, другая - только false, причем писать одновременно они не могут. "Так защищаться можно"  Улыбающийся
Ну, если в качестве флага вы используете int, то нельзя. Вообще-то, если я не ошибаюсь, язык не гарантирует атомарности операций записи, поэтому есть ненулевая вероятность нарваться на неприятности. Отсюда и мой вопрос.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #18 : Сентябрь 08, 2018, 13:57 »

Ну, если в качестве флага вы используете int, то нельзя. Вообще-то, если я не ошибаюсь, язык не гарантирует атомарности операций записи, поэтому есть ненулевая вероятность нарваться на неприятности. Отсюда и мой вопрос.
Популярное заблуждение "атомарность = хорошо"  Улыбающийся Типичная ошибка
Код
C++ (Qt)
if (writeFlag) {  
DoSomethng(..);
}
Обычно в multi-threading такие проверки - мертвому припарка. Чтение writeFlag может быть хоть 100 раз атомарно, но если др нитка его пишет - креш. Атомарность гарантирует лишь что текущее/моментальное значение будет прочитано/записано верно, но уже на момент выполнения след команды (начало DoSomethng) значение writeFlag может оказаться уже иным.

Примерим это к данному случаю
Код
C++ (Qt)
if (m_writeFlag) return;
Что произойдет если m_writeFlag было true а потом моментально стало false (UI изменило)? Ничего плохого (return), ну пропустим след опрос по таймеру т.к. предыдущий не успел. Вот если бы наоборот (было false - стало true) - тогда бы получили по дюнделю. Но в том-то и дело что UI пишет только  false (никогда true).

Предположим даже что запись m_writeFlag НЕ атомарна (напр тип double который в 32-битах может присваиваться как 2 инта). Но если пишется ноль - и такая запись не может изменить текущий "ноль" на "не ноль".
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #19 : Сентябрь 10, 2018, 11:11 »

Ну вот, наверное не дошло, но выяснить стесняются  Улыбающийся Пожуем еще разок
Код
C++ (Qt)
// Нитка делает опрос, сохраняет рез-т в мапе (m_data)
// и посылает сигнал в главную нитку
void Checker::timerEvent( QTimerEvent * )
{
 if  (!m_writeFlag) {
  m_writeFlag = true;
  BuildMap(m_data);
  emit newData(this);
}
}
Код
C++ (Qt)
// Главная Нитка использует мапу и после этого сбрасывает флажок
void SomeWindow::SlotNewData( Checker * checker )
{
// обновляем UI используя checker->m_data
// ...
  checker->m_writeFlag = false;
}
Когда первая нитка получает событие таймера и m_writeFlag == false, значит или это стартовый ноль или главная нитка уже закончила использование предыдущей мапы, а начать новое не сможет т.к. сигнал newData исходит из первой. Поэтому без разницы как пишется флажок - атомарно или нет, если он оказался сброшен, то никакая другая нитка его уже не изменит, и мы можем смело писать новую мапу

Ну а можно и не включать моск, а просто поставить QMutexLocker (или QMutex::tryLock) перед чтением и записью.
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #20 : Сентябрь 10, 2018, 12:00 »

Интересно, с какими типами переменных такие операции атомарны?
std::atomic
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #21 : Сентябрь 12, 2018, 00:21 »

Ну вот, наверное не дошло, но выяснить стесняются  Улыбающийся Пожуем еще разок
Да не, не стесняются, просто лишен был на 3 дня интернета) Да и разжевывать тут нечего, есть уже вмятина от этого садового инструмента.
Просто применять решение, которое работает для данного конкретного случая (типа, тут играем, здесь рыбу заворачивали) не здорово. Потом забудешь, для какого.
Поэтому лучше включить "моск" и делать
Ну а можно и не включать моск, а просто поставить QMutexLocker (или QMutex::tryLock) перед чтением и записью.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Сентябрь 12, 2018, 03:33 »

Да не, не стесняются, просто лишен был на 3 дня интернета) Да и разжевывать тут нечего, есть уже вмятина от этого садового инструмента.
Просто применять решение, которое работает для данного конкретного случая (типа, тут играем, здесь рыбу заворачивали) не здорово. Потом забудешь, для какого.
Этот садовый инструмент называется lock-free. С чисто практической, утилитарной точки зрения - да, он заслуживает осуждения именно по причине своей сложности, мозголомности (хотя код и выглядит простым). Ошибиться очень легко, напр
Код
C++ (Qt)
// Главная Нитка использует мапу и после этого сбрасывает флажок
void SomeWindow::SlotNewData( Checker * checker )
{
// обновляем UI используя checker->m_data
// ...
  checker->m_writeFlag = false;
// ..
// здесь чем-то увлекся, забыл и сбросил флажок еще раз
// ..
  checker->m_writeFlag = false;
}
И вот уже очень мерзкий баг который вылезет не сразу

Поэтому лучше включить "моск" и делать
Ну если это "включить"  Улыбающийся
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #23 : Сентябрь 12, 2018, 09:58 »

Ну если это "включить"  Улыбающийся
Да. Потому что дальше надо много думать, чтобы избежать взаимных блокировок)))
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.163 секунд. Запросов: 22.