атомарна операція

Атомарна (атом від грец. Atomos - неподільне) операція - операція, яка або виконується цілком, або не виконується зовсім; операція, яка не може бути частково виконана і частково не виконана.

У даній статті описуються найпростіші атомарні операції (інкремент, читання, запис і т. П.), Хоча термін може відноситься до більш високорівневих операцій, таким як, наприклад, серія запитів до СУБД в рамках однієї транзакції.

Атомарні операції використовуються в багатопроцесорних комп'ютерах і в багатозадачних операційних системах для забезпечення доступу декількох процесів і / або декількох потоків одного процесу до поділюваних між ними ресурсів. Атомарна операція виконується тільки одним потоком.

Атомарність операцій може забезпечуватися апаратно (апаратурою) і програмно (програмним кодом). У першому випадку використовуються особливі машинні інструкції. атомарность виконання яких гарантується апаратурою. У другому випадку використовуються спеціальні програмні засоби синхронізації. за допомогою яких здійснюється блокування ресурсу,; після блокування виконується операція, яку потрібно виконати атомарному. Блокування являє собою атомарному операцію, яка або надає ресурс в користування потоку. або повідомляє потоку про те, що ресурс вже використовується іншим потоком або процесом (зайнятий).

Асемблерні інструкції і атомарность Правити

Машинні інструкції, виконання яких завжди можна вважати атомарним:

Машинні інструкції, які не є атомарними:

Атомарні інструкції процесорів x86 Правити

Атомарні інструкції процесорів архітектури x86:

  • CMPXCHG, CMPXCHG8B, CMPXCHG16B - основна атомарна інструкція процесорів x86. виконує порівняння і обмін. При використанні з префіксом LOCK атомарному порівнює значення змінної з вказаним значенням і, в залежності від результату порівняння, записує в змінну вказане значення або нічого не робить. Є основою реалізації всіх безблокіровочних алгоритмів. часто використовується в реалізації спінлоков. RWLock'ов і практично всіх високорівневих синхронізуючих елементів, таких як семафори, м'ютекси, події та ін .;
  • XCHG - операція для читання даних з регістра або пам'яті і запису даних в регістр або пам'ять. На процесорах x86 виконується атомарному. Часто використовується в реалізації спінлоков.

Крім того, багато машинні інструкції виду «читання-модифікація-запис» виконуються атомарному при наявності префікса LOCK (опкод 0xF0), наприклад, такі:

Префікс LOCK викликає блокування доступу до пам'яті на час виконання інструкції. Блокування може поширюватися на область пам'яті ширше, ніж довжина операнда, наприклад, на довжину лінії кеша.

Атомарні інструкції процесорів RISC Правити

Особливістю процесорів архітектури RISC є відсутність інструкцій виду «читання-модифікація-запис». У процесорах RISC з архітектурою DEC Alpha. PowerPC. MIPS і ARM (ARMv6 і старше) підтримується механізм неблокуючим ексклюзивного доступу до пам'яті. Атомарні операції реалізуються з використанням пари інструкцій ексклюзивного читання-запису LL і SC наступним чином:

  • завантаження з позначкою (LL - load linked);
  • зміна даних;
  • спроба запису (SC - store conditional).

Перша інструкція (LL) завантажує дані з комірки пам'яті в регістр і позначає комірку, як осередок для ексклюзивного доступу. Далі проводяться необхідні зміни даних у регістрі. Запис даних з регістра в пам'ять (SC) проводиться тільки в тому випадку, якщо значення комірки пам'яті не змінювалося. Якщо значення змінювалося, три операції (LL, зміна даних та SC) слід повторити.

Атомарні інструкції і компілятори Правити

Компілятори мов високого рівня. як правило, не використовують при генерації коду атомарні інструкції, оскільки, по-перше, атомарні операції у багато разів більше ресурсомісткі, ніж звичайні, а по-друге, у компілятора немає інформації про те, коли доступ до даних повинен здійснюватися атомарному (так як навіть модифікатор volatile для змінної в мовах C / C ++ не означає реальної необхідності застосування атомарних операцій). У разі необхідності програміст може використовувати атомарні інструкції одним із таких способів:

  1. вставити атомарні інструкції в код, використовуючи наданий компілятором асемблер. наприклад, GCC Inline Assembly компілятора gcc;
  2. використовувати функції, що надаються компілятором і викликають атомарні інструкції, наприклад, функції сімейств __builtin_ або __sync_ компілятора gcc;
  3. використовувати функції, що надаються бібліотеками і викликають атомарні інструкції, наприклад, функції бібліотеки Glib;
  4. використовувати мови програмування, що підтримують атомарность, наприклад, мови стандартів C11 і C ++ 14. підтримують типи _Atomic і atomic і функції сімейства atomic_.

Схожі статті