Вы не сказали, на каком языке. Я собираюсь притвориться, что это C ++.
Я использую разные мьютексы для каждой переменной ...
Звучит подозрительно.
Ваши потоки общаются друг с другом путем обновления общего состояния. При правильном использовании мьютекс делает две вещи:
- Это гарантирует, что после того, как поток А обновит общее состояние, другие потоки смогут увидеть, что было изменено, и
- Это гарантирует, что другие потоки не увидят изменения, пока изменение не будет завершено .
Если поток может существенно изменить состояние программы, записав одно значение uint16_t
, тогда вам не нужен мьютекс для этого. Просто измените тип переменной на atomic<uint16_t>.
. Делая ее атомарной, вы увидите, что другие потоки смогут увидеть это изменение. И вам не нужно беспокоиться о полноте. Это триал: каждый другой поток должен видеть либо старое, либо новое значение. Других возможностей нет.
Вам нужно mutex
, когда ситуация более сложная. Предположим, у вас есть три переменные:
int a, b, c;
И, предположим, есть правило, что a+b+c
всегда должно равняться нулю. Такое правило называется инвариантом . Теперь никоим образом поток не может юридически изменить только одну из этих трех переменных. Но, если он пытается изменить два из них подряд, всегда есть вероятность, что какой-то другой поток может взглянуть на них в самый неподходящий момент и увидеть их в несогласованном состоянии (то есть в состоянии, которое нарушает инвариантно.)
Создание переменных atomic
не решит проблему. И создание отдельного мьютекса для каждой переменной не решит проблему. Вам нужен один мьютекс, целью которого является защита инварианта. Вам нужен каждый поток, который обновляет a
, b
и / или c
, чтобы заблокировать этот один мьютекс при каждом изменении; и вам нужно, чтобы каждый поток, который ожидает, что инвариант имеет значение true, блокирует один и тот же мьютекс всякий раз, когда он смотрит на них .