Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
Заблокирован
1

Атомарна ли операция присваивания и чтения POD данных?

29.05.2013, 11:43. Показов 1574. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Привет! Терзают меня сомнения по поводу необходимости критической секции в следующие ситуации:
Есть класс, в нём есть поля простых типов данных, например:
C++ (Qt)
1
2
3
4
public:
   int x;
   short y;
   char* string;
Так же есть два потока, один постоянно читает эти данные, а другой - постоянно записывает.
Вот интересно, нужна ли тут критическая секция, ведь на сколько мне кажется, операции записи и присваивания простых данных - атомарны, тоесть выполняются за один такт процессора, ну тоесть просто в один регистр процессора записываются или оттуда же читаются. Тоесть в принципе в однопроцессорной машине думаю проблем быть не должно без критических секций, т.к. эти операции не могут одновременно как бы выполняться, так? А в многопроцессорной машине? А в однопроцессорной, но многоядерной?
А если среди данных присутствует std::string ? тоесть как бы один поток стринг эстелевский пишет, а другой читает?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.05.2013, 11:43
Ответы с готовыми решениями:

Атомарна ли операция присваивания в однопроцессорной машине?
? :) Добавлено через 1 минуту судя по это - атомарна :) 18: int a = 5; 0117C760 C7 45...

Атомарна ли операция битового сдвига?
Система: Win7 x64. Один проц Intel i7 3770k. Предположим, что я в студии собираю 64-х битным...

Операция присваивания
Чем отличается операция присваивания "/=" от "=" ?

Операция присваивания (=)
Добрый день, интересует вот что: правильно ли я считаю, что в int x = .0 + 1F + 4L; 1) Сперва...

10
1665 / 1134 / 80
Регистрация: 21.08.2008
Сообщений: 4,734
Записей в блоге: 1
29.05.2013, 11:46 2
Цитата Сообщение от FarStar Посмотреть сообщение
операции записи и присваивания простых данных - атомарны
вроде только для булевых.
0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
29.05.2013, 12:52 3
Нельзя закладываться на якобы атомарность операций. Потому что оптимизирующий компилятор может так перемешать ассемблерные инструкции, что ой-ей-ей!
0
Заблокирован
29.05.2013, 13:59  [ТС] 4
Цитата Сообщение от CheshireCat Посмотреть сообщение
Нельзя закладываться на якобы атомарность операций. Потому что оптимизирующий компилятор может так перемешать ассемблерные инструкции, что ой-ей-ей!
да, я так тоже подумал, по этому буду лепить везде критические секции, это ж не сложно )
0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
29.05.2013, 14:46 5
Не всегда это нужно. В Win API, например, есть семейство Interlocked..()-функций. Вот они гарантируют атомарность операции.
1
Заблокирован
29.05.2013, 17:02  [ТС] 6
Цитата Сообщение от CheshireCat Посмотреть сообщение
В Win API, например, есть семейство Interlocked..()-функций
А... про них то я и забыл ... :-) данке
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
30.05.2013, 13:34 7
На архитектурах IA-32 и AMD64 операции чтения и записи в память атомарны для
типов BYTE (1 байт), WORD (слово, 2 байта), DWORD (двойное слово, 4 байта) и
QWORD (четверное слово, 8 байт), последнее только в 64-битном режиме работы
процессора (Long Mode). При условии, что данные корректно выровнены или
находятся в пределах одной кэш-линии.

Некоторые встроенные типы языков C и C++, такие как char, int, указатель и др.,
естественным образом отображаются на типы BYTE/WORD/DWORD/QWORD, поэтому их можно
смело читать и писать из разных потоков, не боясь получить промежуточное значение.
Современные компиляторы достаточно умны и не станут разбивать, скажем, запись в
WORD-переменную на две BYTE-операции. Фактически, все сведется к инструкции mov.

Выравнивание данных обеспечивается как компилятором, так и системой: стековые
переменные и члены структур выравниваются компилятором, при выделении памяти с
помощью malloc/new/VirtualAlloc и т.п. аллокаторы выдают уже выровненные адреса.

Все это справедливо исключительно для примитивных операций, которые на уровне
машинных команд реализуются в виде "memory-register" или "register-memory".
Операции класса "read-modify-update", такие как инкремент, уже не будут атомарными.
Компилятор может реализовать инкремент как "mov, add 1, mov". Да и инструкция
inc сама по себе тоже не является атомарной, так как реализуется через микрокод.
В этих случаях необходимо пользоваться всякими <atomic> и Interlocked-функциями.

Но это все атомарность на уровне CPU, а есть еще логическая атомарность, которая
приобретает смысл в контексте определенных идей, заложенных программистом.
Например, класс динамического массива, хранящий указатель на буфер памяти и поля
num_items и capacity, по определению должен рассматриваться, как неделимое целое:
ни в один момент времени не должно быть несогласованности между значениями полей.
То, что мы можем сначала атомарно обновить одно поле, потом атомарно второе и так
далее, в данном случае нам ничем не поможет, атомарной должна быть вся операция
обновления класса. Вот здесь и нужны такие вещи, как критические секции, спин-
блокировки, мьютексы и т.п.

Цитата Сообщение от FarStar Посмотреть сообщение
Тоесть в принципе в однопроцессорной машине думаю проблем
быть не должно без критических секций, т.к. эти операции не могут одновременно
как бы выполняться, так? А в многопроцессорной машине?
А в однопроцессорной, но многоядерной?
Правила атомарности одинаковы для любых топологий - однопроцессорные, многопроцессорные,
многоядерные, многоядерные с Hyper-Threading и т.д. Они принципиально не менялись
еще со времен Intel 486.

Цитата Сообщение от FarStar Посмотреть сообщение
А если среди данных присутствует std::string ?
то есть как бы один поток стринг эстелевский пишет, а другой читает?
Зависит от реализации STL.
Например, STL-классы в Visual C++ потокобезопасны только на чтение.
Множество потоков могут читать данные из них, но если есть хотя бы один пишущий, то
нужна синхронизация. Кстати, необязательно лепить везде критические секции, можно
использовать "readers-writers locks", спин-блокировки, lock-free и т.п.

Цитата Сообщение от CheshireCat Посмотреть сообщение
Нельзя закладываться на якобы атомарность операций.
Потому что оптимизирующий компилятор может так перемешать ассемблерные
инструкции, что ой-ей-ей!
Если перемешать две ассемблерные инструкции mov, атомарными от этого они быть не перестанут.
А если важна видимость данных и их порядок, тогда следует применять volatile, компиляторные
барьеры и барьеры памяти.
1
Заблокирован
25.09.2013, 21:17 8
Подниму ка я старую тему.
Убежденный, исходя из выше сказанного, осмелюсь предположить, что если я определяю в глобальном пространстве переменную типа BYTE, WORD, DWORD или QWORD, то есть объявлю её статический на этапе компиляции, а не динамический при помощи new, то она будет корректно выровнена и будет находится в пределах одной кэш линии, в случае её записи и чтения из кучи других потоков?
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
25.09.2013, 21:49 9
В стандарте языка С++ описана такая вещь, как "alignment requirements" -
требования к выравниванию данных. Данные выравниваются по адресам, кратным
размеру этих данных. Например, int размещается по адресу, кратному 4 байтам,
потому что sizeof (int) == 4. То есть, глобальная ли переменная, локальная,
статическая - не важно, она все равно будет правильно выровнена компилятором.
Кстати, new тоже имеет определенные гарантии выравнивания.
1
Заблокирован
25.09.2013, 22:04 10
Большое спасибо! Теперь буду смело перезаписывать BYTE, WORD, DWORD, QWORD, char, int из разных потоков без синхронизации...

Единственное что осталось уточнить. Если я аллоцирую память под массив, например DWORD test = new DWORD[10], будут ли элементы массива так сказать придерживаться coalesced memory, тоесть идти в памяти друг за другом по порядку по умолчанию? А если статический DWORD test[10]; ? И если я к 10-и этим элементам из разных 10-и потоков буду "одновременно" обращаться придерживаясь правила - что первый поток обращается только к 1-му элементу массива, второй поток - только ко второму элементу массива и тд, нормально ли это будет работать без не предвиденного результата?
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
25.09.2013, 22:11 11
Цитата Сообщение от newbie666 Посмотреть сообщение
Теперь буду смело перезаписывать BYTE, WORD, DWORD, QWORD, char, int из разных потоков без синхронизации...
Цитата Сообщение от Убежденный Посмотреть сообщение
На архитектурах IA-32 и AMD64 операции чтения и записи в память атомарны для
типов BYTE (1 байт), WORD (слово, 2 байта), DWORD (двойное слово, 4 байта) и
QWORD (четверное слово, 8 байт), последнее только в 64-битном режиме работы
процессора (Long Mode).
Это справедливо и для других типов данных размера большего, чем int - в 32-битных
процессах доступ к ним не может быть атомарным без использования внешних
средств синхронизации.
1
25.09.2013, 22:11
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.09.2013, 22:11
Помогаю со студенческими работами здесь

Операция присваивания
Вот что говорится в хелпе про составное присванивание. Форма e1 op= e2 ведет себя как e1 = e1 op...

операция присваивания
Столкнулся с глупой проблемой, может кто объяснить, как в таком случае делается присваивание и в...

Преобразование типов в операция присваивания
Добрый вечер, форумчане. Я новичок в программировании, изучаю C++. Читаю книгу &quot;C++ Шаг за шагом&quot; -...

Конструктор копирования и операция присваивания в классе
Народ, вот есть такие объявления(motto - объект класса StringBad): StringBad ditto(motto);...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru