Я пытался установить инвариант между двумя атомными счетчиками в одном потоке, гарантируя, что этот инвариант был сохранен во время чтения в другом потоке без использования мьютекса.
Тем не менее, глядя на код, кажется, что я только что реализовал какой-то алгоритм блокировки, используя два атомных счетчика (с риском, который я только что испортил).
Можно ли разделить инвариант между потоками без использования стратегии блокировки?
РЕДАКТИРОВАТЬ: термин инвариант не может быть адекватным.
Допустим, у меня есть две переменные а также б, в какой-то момент выполнения программы поток A множество а также б к некоторым различным значениям, и после этого я хотел бы, чтобы поток B загружал значение хранится в A, а затем загрузить б, загруженное значение б тот, который хранится в A, а не значение, сохраненное позже в б.
Можно ли разделить инвариант между потоками без использования стратегии блокировки?
Нет.
Зачем? Представьте себе следующий сценарий: нить X и Y, счетчики a
а также b
,
Поток X пишет в a
а также b
, что приводит к разрыву инварианта. Предполагая, что поток Y пытается прочитать a
а также b
, в то время как инвариант нарушен и без какой-либо стратегии блокировки.
В этом случае поток Y может читать устаревшие (или слишком свежие) данные, так как a
может быть значением, которое X написал сейчас, или предыдущим. То же самое означает b
,
Это классическая ошибка в многопоточности, которая приводит к гонки данных.
Это похоже на пример двойного связанного списка Вот. В этом случае потоки X и Y существуют и управляют двойным связанным списком. Один из инвариантов заключается в том, что если мы следуем по следующему указателю от одного узла (1) к другому (2), предыдущий указатель с этого узла (2) указывает на первый узел (1).
Предполагая, что поток X удаляет узел списка, поток Y пытается прочитать в этой точке и может вызвать проблемы, поскольку существует вероятность того, что указатели предыдущего и следующего узлов узла, которые будут удалены X, еще не установлены (таким образом, инвариант прерывается в то время, когда поток Y пытается прочитать список).
Других решений пока нет …