Чтение онлайн

на главную - закладки

Жанры

QNX/UNIX: Анатомия параллелизма
Шрифт:

Именно для безопасного манипулирования данными в параллельной среде QNX API и вводятся атомарные операции. Десять атомарных функций делятся на две симметричные группы по виду своего именования и логике функционирования. Все атомарные операции осуществляются только над одним типом данных

unsigned int
, но, как будет показано далее, это не такое уж и сильное ограничение. Сам объект, над которым осуществляется атомарная операция (типа
unsigned int
), — это самая обычная переменная целочисленного типа, только описанная с квалификатором
volatile
.

Помимо

атомарных операций над этой переменной могут выполняться любые другие действия, которые можно считать безопасными в многопоточной среде: инициализация, присваивание значений, сравнения. Более того, при выходе программы за область возможного многопоточного доступа к этой переменной она может далее использоваться любым традиционным и привычным образом.

Важно также отметить, что термин «атомарность» относится не к особым свойствам некоторого объекта данных, а к ограниченному ряду операций, которые можно безопасно выполнять над этим объектом в многопоточной среде.

Общий вид прототипов каждой из двух групп атомарных операций следующий:

void atomic_*(volatile unsigned *D, unsigned S);

unsigned atomic_*_value(volatile unsigned *D, unsigned S);

где вместо

*
должно стоять имя одной из пяти операций (таким алгоритмом и обеспечивается 10 различных атомарных функций):

add
— добавить численное значение к операнду;

sub
— вычесть численное значение из операнда;

clr
— очистить битыв значении операнда (выполняется побитовая операция (
*D) &= ~S
);

set
— установить битыв значении операнда (выполняется побитовая операция (
*D) |= S
);

toggle
— инвертировать битыв значении операнда (выполняется побитовая операция (
*D) ^= S
);

D
— именно тот объект, над которым осуществляется атомарная операция;

S
— второй операнд осуществляемой операции.

Две формы атомарных функций для каждой операции отличаются тем, что первая из них выполняет операцию без возврата значения, а вторая возвращает значение, которое операнд

D
имел до выполнения операции (т.e. прежнее значение, как это делают, например, префиксные операции инкремента
++D
и декремента
– -D
, в отличие от постфиксных
D++
и
D--
).

Зачем нужны две формы для операции? Техническая документация QNX утверждает, что вторая форма может выполняться дольше. Справедливость этого утверждения и насколько дольше выполняется вторая форма, мы скоро увидим на примерах.

Итак, у нас есть 10 функций для выполнения пяти атомарных операций:

atomic_add atomic_add_value

atomic_sub atomic_sub_value

atomic_clr atomic_clr_value

atomic_set atomic_set_value

atomic_toggle atomic_toggle_value

Как используются атомарные операции? Обычно для предотвращения одновременного изменения некоторого счетчика индекса мы вынуждены создавать критическую секцию, обозначая ее, скажем, операциями над мьютексом. В частности, в следующем примере нам необходимо из различных потоков последовательно дописывать некоторые байтовые результаты в единый буфер:

// глобальные описания, доступные всем потокам

const unsigned int N = ...

uint8_t buf[N];

// индекс текущей позиции записи

unsigned int ind = 0;

// общий мьютекс, доступный каждому из потоков

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

...

// выполняется в каждом из потоков:

uint8_t res[M]; // результат некоторой операции

unsigned int how = ... // реальная длина этого результата

pthread_mutex_lock(&mutex);

memcpy((void*)buf + ind, (void*)res, how);

ind += how;

pthread_mutex_unlock(&mutex);

Используя атомарные операции, мы можем этот процесс записать так (все глобальные описания остаются неизменными):

// глобальные описания, доступные всем потокам

...

// индекс текущей позиции записи

volatile unsigned int ind = 0;

...

// выполняется в каждом из потоков:

uint8_t res[M]; // результат некоторой операции

unsigned int how = ... // реальная длина этого результата

memcpy((void*)buf + atomic_add_value(ind, how), (void*)res, how);

Или даже так:

// глобальные описания, доступные всем потокам

...

// указательтекущей позиции записи:

volatile unsigned int ind = (unsigned int)buf;

...

// выполняется в каждом из потоков:

memcpy((void*)atomic_add_value(ind, how), (void*)res, how);

В последнем случае это, конечно, трюкачество, построенное на том, что в 32-разрядной архитектуре представления указателя и переменной

unsigned int
совпадают, но это «работающее трюкачество» и работающее иногда весьма эффективно.

Поделиться:
Популярные книги

Курсант: назад в СССР 2

Дамиров Рафаэль
2. Курсант
Фантастика:
попаданцы
альтернативная история
6.33
рейтинг книги
Курсант: назад в СССР 2

На границе империй. Том 9. Часть 3

INDIGO
16. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 3

Ведьма и Вожак

Суббота Светлана
Фантастика:
фэнтези
7.88
рейтинг книги
Ведьма и Вожак

Дурашка в столичной академии

Свободина Виктория
Фантастика:
фэнтези
7.80
рейтинг книги
Дурашка в столичной академии

Барон устанавливает правила

Ренгач Евгений
6. Закон сильного
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
Барон устанавливает правила

Провинциал. Книга 3

Лопарев Игорь Викторович
3. Провинциал
Фантастика:
космическая фантастика
рпг
аниме
5.00
рейтинг книги
Провинциал. Книга 3

Темный Лекарь

Токсик Саша
1. Темный Лекарь
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Темный Лекарь

Вираж бытия

Ланцов Михаил Алексеевич
1. Фрунзе
Фантастика:
героическая фантастика
попаданцы
альтернативная история
6.86
рейтинг книги
Вираж бытия

Газлайтер. Том 1

Володин Григорий
1. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 1

Я – Орк

Лисицин Евгений
1. Я — Орк
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я – Орк

Совок 9

Агарев Вадим
9. Совок
Фантастика:
попаданцы
альтернативная история
7.50
рейтинг книги
Совок 9

Последняя Арена 11

Греков Сергей
11. Последняя Арена
Фантастика:
фэнтези
боевая фантастика
рпг
5.00
рейтинг книги
Последняя Арена 11

По осколкам твоего сердца

Джейн Анна
2. Хулиган и новенькая
Любовные романы:
современные любовные романы
5.56
рейтинг книги
По осколкам твоего сердца

Тринадцатый III

NikL
3. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый III