Я опубликовал ошибку, в которой я думал, что это законная многопоточная проблема, но на самом деле это была просто плохая логика.Я решил ошибку, как только отправил.Вот проблемные строки и ответ
unsigned int lockedaquired = 0;
Я инициализировал lockaquired равным 0, а затем после того, как добавил оператор if, чтобы пропустить дорогостоящую операцию выполнения CAS.Эта оптимизация вызвала его выпадение из цикла while в критическую секцию.Изменение кода на
unsigned int lockedaquired = 1;
Устраняет проблему.В коде, который я обнаружил, есть еще одна скрытая проблема (я действительно больше не должен кодировать поздно ночью).Кто-нибудь замечает точку с запятой после оператора if в критическом разделе?Вздох ...
if(*ctxt->ticket > 0);
(*ctxt->ticket)--;
Это должно быть
if(*ctxt->ticket > 0)
Кроме того, Бен Джексон указал, что поток, вероятно, будет в критической секции, когда мы сбросим тикет в eNumThreads.Хотя это прекрасно в этом примере кода, если вы примените его к проблеме, где вам нужно было выполнять больше операций, это может быть небезопасно, потому что потоки не работают в режиме ожидания, так что имейте это в виду, если вы примените это к своемуcode.
Последнее замечание: если кто-то решит использовать этот код для собственной реализации мьютекса, помните, что ваш основной поток драйверов вращается вхолостую.Если вы выполняете большую работу в критической секции, которая занимает много времени, а количество билетов очень велико, подумайте о том, чтобы уступить потоку, чтобы другое программное обеспечение могло использовать ЦП во время его ожидания.Кроме того, рассмотрите возможность использования спин-блокировки, если критическая секция велика.
Спасибо