32 ビットのアトミック変数を使用した 64 ビットのアトミック カウンターの実装
質問:
次を使用して 64 ビット アトミック カウンタを設計および実装する32 ビットのアトミック変数。カウンタには単一のライター (シグナル ハンドラー) と複数のリーダーがあります。
コード:
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); } };
答え:
提供されたコードは、32 ビットのアトミック変数を使用した 64 ビットのアトミック カウンタの正しい実装です。これは、カウンタの上位半分と下位半分の一貫性を維持するために世代カウントを使用する SeqLock として知られる技術を使用します。
読み取り操作では、処理中にループを使用してカウンタの正しい状態を取得します。リーダーとライターの間の潜在的な競合状態。書き込み操作は、正しい動作を保証するためにメモリの順序付けを使用して、カウンタの上位部分と下位部分の両方をアトミックにインクリメントします。
実装の改善:
提供されたコードは正しいですが、 、
代替デザイン:
必要性を排除した代替デザインアトミックな RMW 操作では、揮発性の uint64_t と std::atomic
以上が32 ビットのアトミック変数のみを使用して 64 ビットのアトミック カウンターを実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。