Мьютексы с переменными в структуре - PullRequest
0 голосов
/ 02 мая 2018

Я работаю над проектом, который использует несколько потоков, которые могут получить доступ к общей структуре, содержащей несколько переменных.

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

Кроме того, учитывая, что в моей структуре есть переменные uint16_t, есть ли какие-либо дополнительные меры, которые я должен предпринять, чтобы гарантировать согласованность данных между потоками из-за выравнивания памяти и нескольких переменных, хранящихся в одном и том же регистре данных?

Спасибо.

1 Ответ

0 голосов
/ 03 мая 2018

Вы не сказали, на каком языке. Я собираюсь притвориться, что это C ++.

Я использую разные мьютексы для каждой переменной ...

Звучит подозрительно.

Ваши потоки общаются друг с другом путем обновления общего состояния. При правильном использовании мьютекс делает две вещи:

  • Это гарантирует, что после того, как поток А обновит общее состояние, другие потоки смогут увидеть, что было изменено, и
  • Это гарантирует, что другие потоки не увидят изменения, пока изменение не будет завершено .

Если поток может существенно изменить состояние программы, записав одно значение uint16_t, тогда вам не нужен мьютекс для этого. Просто измените тип переменной на atomic<uint16_t>.. Делая ее атомарной, вы увидите, что другие потоки смогут увидеть это изменение. И вам не нужно беспокоиться о полноте. Это триал: каждый другой поток должен видеть либо старое, либо новое значение. Других возможностей нет.

Вам нужно mutex, когда ситуация более сложная. Предположим, у вас есть три переменные:

int a, b, c;

И, предположим, есть правило, что a+b+c всегда должно равняться нулю. Такое правило называется инвариантом . Теперь никоим образом поток не может юридически изменить только одну из этих трех переменных. Но, если он пытается изменить два из них подряд, всегда есть вероятность, что какой-то другой поток может взглянуть на них в самый неподходящий момент и увидеть их в несогласованном состоянии (то есть в состоянии, которое нарушает инвариантно.)

Создание переменных atomic не решит проблему. И создание отдельного мьютекса для каждой переменной не решит проблему. Вам нужен один мьютекс, целью которого является защита инварианта. Вам нужен каждый поток, который обновляет a, b и / или c, чтобы заблокировать этот один мьютекс при каждом изменении; и вам нужно, чтобы каждый поток, который ожидает, что инвариант имеет значение true, блокирует один и тот же мьютекс всякий раз, когда он смотрит на них .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...