Heim >Backend-Entwicklung >C++ >Wie implementiert man einen 64-Bit-Atomzähler nur mit 32-Bit-Atomzählern?

Wie implementiert man einen 64-Bit-Atomzähler nur mit 32-Bit-Atomzählern?

Barbara Streisand
Barbara StreisandOriginal
2025-01-04 16:52:39566Durchsuche

How to Implement a 64-Bit Atomic Counter Using Only 32-Bit Atomics?

Implementierung eines 64-Bit-Atomzählers mit 32-Bit-Atomics

Einführung:

Dieser Artikel befasst sich mit dem Entwurf und der Implementierung eines 64-Bit-Atomzählers unter Verwendung 32-Bit-Atomoperationen. Ziel ist es, einen effizienten, sperrfreien Zugriff auf einen gemeinsamen Zähler zu ermöglichen, der sich besonders für Szenarien mit mehreren Lesern und einem einzigen Schreiber eignet.

Designüberlegungen:

Der Vorschlag Das Design basiert auf dem Konzept eines „SeqLock“, das eine 32-Bit-Generationszählung nutzt, wobei ein niedriges Bit als Lesesperre verwendet wird Mechanismus.

Code-Implementierung:

class counter {
    atomic<uint32_t> lo_;
    atomic<uint32_t> hi_;
    atomic<uint32_t> gen_;

    uint64_t read() const {
        auto acquire = memory_order_acquire;
        uint32_t lo, hi, gen1, gen2;
        do {
            gen1 = gen_.load(acquire);
            lo = lo_.load(acquire);
            hi = hi_.load(acquire);
            gen2 = gen_.load(acquire);
        } while (gen1 != gen2 || (gen1 & 1));
        return (uint64_t(hi) << 32) | lo;
    }

    void increment() {
        auto release = memory_order_release;
        gen_.fetch_add(1, release);
        uint32_t newlo = 1 + lo_.fetch_add(1, release);
        if (newlo == 0) {
            hi_.fetch_add(1, release);
        }
        gen_.fetch_add(1, release);
    }
};

Designbewertung:

  1. Korrektheit: Das Design bietet eine gültige Implementierung eines 64-Bit-Atomzählers, verhindert Race Conditions und stellt sicher, dass alle Threads konsistent sind Werte.
  2. Effizienz: Die Verwendung von 32-Bit-Atomics anstelle von 64-Bit-Atomics verbessert die Leistung, insbesondere in Systemen, in denen 64-Bit-Atomic-Operationen teuer sind.
  3. Sperrenfreiheit: Das SeqLock-Design macht Sperren überflüssig, was zu einem hochgradig gleichzeitigen Zugriff auf die führt Zähler.

Alternative Lösung:

Es ist wichtig zu beachten, dass atomare Lese-, Änderungs- und Schreibvorgänge (RMW) für den Inkrementierungsvorgang möglicherweise nicht erforderlich sind . Ein effizienterer Ansatz besteht stattdessen darin, reine Lade- und Speichervorgänge mit Release-Memory-Reihenfolge zu verwenden:

void increment() {
    auto release = memory_order_release;
    uint64_t count = lo_.load(release) | (uint64_t(hi_.load(release)) << 32);
    count++;
    lo_.store(count & uint32_t(-1), release);
    hi_.store((count >> 32) & uint32_t(-1), release);
}

Schlussfolgerung:

Die vorgeschlagene Implementierung bietet eine effiziente und korrekte Lösung zum Erstellen eines 64-Bit-Atomzählers mit 32-Bit-Atomzählern. Das SeqLock-Design stellt sicher, dass der Zähler ohne Sperren arbeitet und ermöglicht gleichzeitig den gleichzeitigen Betrieb mehrerer Leser und eines einzelnen Schreibers, ohne dass es zu Datenwettläufen kommt.

Das obige ist der detaillierte Inhalt vonWie implementiert man einen 64-Bit-Atomzähler nur mit 32-Bit-Atomzählern?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn