В статье с тем же названием, что и у этого вопроса, авторы описывают, как построить неблокирующую линеаризуемую операцию CAS с несколькими словами, используя только CAS с одним словом. Сначала они вводят операцию двойного сравнения-одиночного обмена - RDCSS следующим образом:
word_t RDCSS(RDCSSDescriptor_t *d) {
do {
r = CAS1(d->a2, d->o2, d);
if (IsDescriptor(r)) Complete(r);
} while (IsDescriptor(r));
if (r == d->o2) Complete(d); // !!
return r;
}
void Complete(RDCSSDescriptor_t *d) {
v = *(d->a1);
if (v == d->o1) CAS1(d->a2, d, d->n2);
else CAS1(d->a2, d, d->o2);
}
где RDCSSDescriptor_t
это структура со следующими полями:
a1
- адрес первого условияo1
- значение ожидается по первому адресуa2
- адрес второго условияo2
- значение ожидается по второму адресуn2
- новое значение записывается по второму адресу
Этот дескриптор создается и инициализируется один раз в потоке, который инициирует операцию RDCSS - ни один другой поток не имеет ссылки на него, пока не выполнится первый CAS1 в функции RDCSS
, что сделает дескриптор достижимым (или активным в терминологии статьи).
Идея алгоритма заключается в следующем: замените вторую ячейку памяти дескриптором, сообщающим, что вы хотите сделать. Затем, учитывая, что дескриптор присутствует, проверьте первую ячейку памяти, чтобы увидеть, изменилось ли ее значение. Если это не так, замените дескриптор во второй ячейке памяти новым значением. В противном случае установите вторую ячейку памяти обратно к старому значению.
Авторы не объясняют, почему !!
в статье необходима строка с комментарием. Мне кажется, что CAS1
инструкции в Complete
функции всегда будут давать сбой после этой проверки, при условии, что нет одновременной модификации. И если произошла одновременная модификация между проверкой и входом CAS Complete
, то поток, выполняющий проверку, все равно должен потерпеть неудачу со своим CAS Complete
, так как одновременная модификация не должна использовать тот же дескриптор d
.
Мой вопрос: можно ли пропустить проверку в функции RDCSSS
, if (r == d->o2)...
если RDCSS по-прежнему поддерживает семантику инструкции двойного сравнения с одним свопом, которая является линеаризуемой и свободной от блокировки ? (строка с !!
комментарием)
Если нет, можете ли вы описать сценарий, где эта строка действительно необходима для обеспечения правильности?
Спасибо.