C ++ 26'da ertelenmiş şikayet: Güncelleme ve tehlikeli bölümleri okumak

Adanali

Active member
C ++ 26'da ertelenmiş şikayet: Güncelleme ve tehlikeli bölümleri okumak


  1. C ++ 26'da ertelenmiş şikayet: Güncelleme ve tehlikeli bölümleri okumak

Rekabetle ilgili yaygın bir sorun, ABA sorunudur. Bu, her zaman aynı değeri döndüren iki kez değişken okuduğunuz anlamına gelir. Bu nedenle, ortada hiçbir şeyin değişmediği sonucuna varır. Ama B.'yi unuttun








Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.













Aşağıdaki senaryo sorunu sunar.

Bir benzetme


Senaryo arabanızda oturuyor ve trafik ışığının yeşil olmasını bekliyor. Bizim durumumuzda, B ve kırmızı için yeşil A içindir. Sıradaki nedir?

  1. Trafik ışığına bakın ve kırmızıdır (a).
  2. Sıkıcı olduğu için akıllı telefonunuzdaki haberlere bakın ve zamanı unutun.
  3. Trafik ışıklarına tekrar bakın. Kahretsin hala kırmızı (a).
İki kontrol arasındaki trafik ışığı yeşilleşti (b). Yani sadece bir tane gibi görünse bile iki kırmızı aşama vardı.

Ya iş parçacığı (süreçler)? Şimdi çok resmi olarak.

  1. Tartışma 1 bir değişkeni okur var A değeri ile
  2. Filo 1 kesintiye uğradı ve iplik 2 gerçekleştirildi.
  3. Tartışma 2 değişkeni değiştirir var A B'den A'ya
  4. Konu 1, yürütme ile başlar ve değişkenin değerini kontrol eder var; Değişkenlerin değerinden beri var Aynı kalıntılar, Konu 1 çalışmasına devam ediyor,
ABA'yı sık sık görmezden gelebilirsiniz.

Atomik çarpma


Aşağıdaki kodda, işlev çoğalır fetch_mult (1) A std::atomic<T>&ki mult Paylaşılır.


// fetch_mult.cpp

#include <atomic>
#include <iostream>

template <typename T>
T fetch_mult(std::atomic<T>& shared, T mult){ // 1
T oldValue = shared.load(); // 2
while (!shared.compare_exchange_strong(oldValue, oldValue * mult)); // 3
return oldValue;
}

int main(){
std::atomic<int> myInt{5};
std::cout << myInt << 'n';
fetch_mult(myInt,5);
std::cout << myInt << 'n';
}


shared.compare_exchange_strong(expected, desired)(3) Aşağıdaki davranışa sahiptir:

  • Karşılaştırma false Sonuçlar, Will expected AÇIK shared ayarlamak.
  • Atom karşılaştırması true Sonuçlar, Will shared Aynı atom işleminde expected ayarlamak.
En önemli gözlem, eski değeri okumak arasında küçük bir zaman penceresi olmasıdır. T oldValue = shared.load (2) ve yeni değerle karşılaştırma (3). Bu nedenle, başka bir iş parçacığı müdahale edebilir oldValue itibaren oldValue İLE anotherValue Ve tekrar oldValue düzenlemek. anotherValue ABA'daki B'dir.

ABA'yı blokları olmayan bir veriye dayanarak göstermek istiyorum.

Bloksuz bir yığın


Zincirli bir liste olarak uygulanan bloklar olmadan bir yığın kullanıyorum. Yığın yalnızca iki işlemi destekler.

  1. Üst nesneyi parmaklayın ve bir işaretçi döndürün.
  2. Belirtilen nesneyi yığın üzerine itin.
Size ABA sorunu hakkında bir fikir vermek için PseudoCodice'deki pop işlemini tanımlamak istiyorum. POP işlemi, başarılı olana kadar bir döngüde aşağıdaki adımları gerçekleştirir.

  • Baş düğümü alın: KAFA
  • Aşağıdaki düğümü alın: HeadNext
  • Yapmak HeadNext yeni kafaya ne zaman KAFA Hala yığının başı
İşte ilk iki yığın düğümü:

Stack: TOP -> head -> headNext -> ...

Aba eylemde


Aşağıdaki yığınla başlayalım:

Stack: TOP -> A -> B -> C

Filo 1 aktiftir ve yığın kafasını çıkarmak istiyor.

İş parçacığı 1 pop algoritmasını bitirmeden önce, iş parçacığı 2 etkinleştirilir.

Stack: TOP -> B -> C

  • Tartışma 2 kaldırıldı B ve Sil B
Stack: TOP -> C

  • Tartışma 2 bir arkaya iter
Stack: TOP -> A -> C

Konu 1, sadece olup olmadığını kontrol etmek için planlanmıştır A == head. A == headhale gelmek headNextYani b, yeni kafaya. Ancak B zaten ortadan kaldırıldı. Bu nedenle, programın belirsiz davranışları vardır.

ABA sorunu için yardım var.

ABA için çare


ABA'nın kavramsal problemini anlamak nispeten kolaydır. Bir düğüm gibi B == headNext başka bir düğüm olsa bile silindi A == headona atıfta bulundu. Sorunumuzun çözümü, düğümün erken iptal edilmesini önlemektir. İşte bazı çözümler.

  • İşaretli bir duruma referans
Düğümün başarıyla değiştirildiği sıklığı belirtmek için bir gün ekleyebilirsiniz. Ancak, “karşılaştırma ve değişim” yöntemi belirli bir noktada başarısız olur, ancak inceleme [/code]GERÇEK[/code] Sonuçlar.

Sonraki üç teknik, ertelenmiş ıslah fikrine dayanmaktadır.

Çöp toplama, değişkenlerin ancak artık gerekli olmadıkları takdirde ortadan kaldırılacağını garanti eder. Umut verici görünüyor, ancak büyük bir dezavantajı var. Çoğu çöp koleksiyoncu bloksuz değildir. Bu nedenle, blokları olmayan bir veriniz var, ancak genel sistem bloksız değil.

Wikipedia'dan: Pointers Tehlike:

Bir tehlike sisteminde, her iş parçacığı, hangi iş parçacığı düğümlerinin erişebileceğini gösteren tehlikeli bölümlerin bir listesini yönlendirir. (Bu “liste” birçok sistemdeki yalnızca bir veya iki öğeyle sınırlı olabilir.) Tehlikeli bölümler listesindeki düğümler başka bir iş parçacığı tarafından değiştirilmemeli veya serbest bırakılmamalıdır. … Bir iş parçacığı bir düğümü kaldırmak istiyorsa, “daha sonra yayınlanması” gereken bir düğüm listesine dayanır, ancak düğümün belleğini yalnızca tehlikeler listesi başka bir iş parçacığı içermiyorsa serbest bırakır. Özel bir çöp toplama iş parçacığı bu pişirme kılavuzu koleksiyonunu gerçekleştirebilir (“Daha sonra sürüm” listesi tüm iş parçacıkları tarafından paylaşılırsa); Alternatif olarak, “Paylaşım” listesinin temizlenmesi, her çalışma iş parçacığı tarafından bir işlemin bir parçası olarak “pop” olarak gerçekleştirilebilir.

RCU için READ COpey UPaul McKenney tarafından geliştirilen ve 2002'den beri Linux çekirdeğinde geliştirilen bir senkronizasyon teknolojisi olan Pdate, neredeyse yazılarak korunan veri yapıları için kullanıldı.

Fikir oldukça basit ve kısaltmayı takip ediyor. Verileri değiştirmek için verilerin bir kopyasını oluşturun ve bu kopyayı değiştirin. Aksine, tüm okuyucular orijinal verilerle çalışır. Okuyucu yoksa, verilerin yapısı tereddüt etmeden kopya ile değiştirilebilir.

Sırada ne var?


Bir sonraki makalemde, ertelenmiş ıslah içeren bloklar olmadan bir yığın uygulayacağım.


(RME)
 
Üst