W artykule o tym samym tytule co tytuł tego pytania, autorzy opisują, jak zbudować nieblokowalną, liniową, wielowątkową operację CAS , używając tylko jednego słowa CAS. Najpierw wprowadzają operację podwójnego porównania-pojedynczej wymiany - RDCSS, jak następuje:
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);
}
gdzie RDCSSDescriptor_t
jest strukturą zawierającą następujące pola:
a1
- adres pierwszego warunkuo1
- wartość oczekiwana pod pierwszym adresema2
- adres drugiego warunkuo2
- wartość oczekiwana pod drugim adresemn2
- nowa wartość do zapisania pod drugim adresem
Ten deskryptor jest tworzony i inicjowany jeden raz w wątku, który inicjuje operację RDCSS - żaden inny wątek nie ma do niego odwołania, dopóki pierwszy CAS1 w funkcji nie RDCSS
powiedzie się, co czyni deskryptor osiągalnym (lub aktywnym w terminologii artykułu).
Algorytm jest następujący: zastąp drugą lokalizację pamięci deskryptorem informującym o tym, co chcesz zrobić. Następnie, biorąc pod uwagę, że deskryptor jest obecny, sprawdź pierwszą lokalizację pamięci, aby zobaczyć, czy jej wartość się zmieniła. Jeśli nie, zastąp deskryptor w drugiej lokalizacji pamięci nową wartością. W przeciwnym razie ustaw drugą lokalizację pamięci z powrotem na starą wartość.
Autorzy nie wyjaśniają, dlaczego linia z !!
komentarzem jest niezbędna w pracy. Wydaje mi się, że po tej kontroli CAS1
instrukcje w Complete
funkcji zawsze się nie udają, pod warunkiem, że nie ma równoczesnej modyfikacji. A jeśli była jednoczesna modyfikacja między czekiem a CAS w Complete
, to wątek wykonujący sprawdzenie powinien nadal zawieść ze swoim CAS w Complete
, ponieważ jednoczesna modyfikacja nie powinna używać tego samego deskryptora d
.
Moje pytanie brzmi: czy można pominąć sprawdzanie funkcji RDCSSS
, if (r == d->o2)...
gdy RDCSS nadal zachowuje semantykę instrukcji podwójnego porównania, pojedynczej zamiany, która jest linearyzowalna i bez blokady ? (linia z !!
komentarzem)
Jeśli nie, czy możesz opisać scenariusz, w którym ta linia jest rzeczywiście konieczna do zapewnienia poprawności?
Dziękuję Ci.