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

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

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

Сообщений: 11445


Просмотр профиля
« : Ноябрь 29, 2014, 17:29 »

Эта тема для тех кто не работал с "многопоточностью". Ничего страшного там нет, но некоторые вещи могут показаться ... ну, немного странными. Вот одна из них, самая простая
Код
C++ (Qt)
if (count > 0)
--count;
else
...
Этот код "непотокобезопасен", т.е. не будет корректно выполняться параллельно 2-мя и более нитками. Никаких крашей не будет, но значение count рано или поздно окажется неверным. Впрочем такие ошибки делают все и много раз, даже если знают об этом  Улыбающийся
Записан
ammaximus
Гость
« Ответ #1 : Ноябрь 29, 2014, 20:08 »

Имеется ввиду, что операция декремента не является атомарной.
Есть ли алгоритм, как определить, что участок потокобезопасен? Мой вариант:
1. Участок защищен мутексом.
2. Атомарность
- Участок состоит из одной атомарной операции.
- Участок состоит из нескольких независимых атомарных операций.
3. Только чтение
- Не используются глобальные переменные.
- Глобальные переменные используются только для чтения.
4. Локальные переменные реентрабельны.

Для потокобезопасности необходимо выполнение условия 1, либо условия 2 и 3 и 4.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Ноябрь 29, 2014, 20:53 »

Хоть один ответил (причем очень неплохо). Только давайте не спешить, для тех кто с этим не работал все не так уж очевидно

Имеется ввиду, что операция декремента не является атомарной.
Нет, хотя и это правильно. Такой код
Код
C++ (Qt)
--count;
Также "not thread-safe". Почему? Процессор исполняет декремент примерно так (псевдокод)

1) загрузить переменную count в регистр
2) отнять от содержимого регистра 1
3) сохранить регистр в переменной (ячейке памяти)

Между 1-2 и/или 2-3 ОС имеет право "вытеснить поток", т.е. передать управление др нитке которая может работать с тем же count. Пример

- count было 5. Загрузили 5 в регистр и тут ОС передал управление
- для др нитки count тоже 5, она взяла и уменьшила его, теперь в ячейке 4
- теперь ОС вернул упр-е первой нитке. Но в регистре-то 5, отняли 1, записали, в ячейке 4

Итог: 2 раза отнимали от 5 единицу, должно быть 3, но имеем 4.  Чтобы не размазывать каждый раз объяснения (типа кто там на регистре) говорят просто "операция не атомарна".  Объявление переменной атомарной страхует от этой проблемы, напр
Код
C++ (Qt)
QAtomicInt count(100);
 
...
--count;
 
Теперь если 100 раз отняли единичку,  count будет четко ноль, хоть отнимали в одной нитке, хоть в 10, хоть как

Однако изначальный пример
Код
C++ (Qt)
if (count > 0)
--count;
else
...
 
По-прежнему not thread-safe, объявление count как QAtomicInt не спасает
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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