32 ビット アトミックを使用した 64 ビット アトミック カウンターの実装
概要:
この記事では、次を使用した 64 ビット アトミック カウンターの設計と実装について説明します。 32 ビットのアトミック操作。これは、共有カウンタへの効率的でロックのないアクセスを提供することを目的としており、特に複数のリーダーと単一のライターを使用するシナリオに適しています。
設計上の考慮事項:
設計は「SeqLock」の概念に基づいており、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); } };
設計評価:
代替解決策:
アトミックな読み取り、変更、書き込み (RMW) に注意することが重要です。 ) 操作は、インクリメント操作には必要ない場合があります。代わりに、より効率的なアプローチは、解放メモリの順序を指定して純粋なロードとストアを使用することです。
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); }
結論:
提案された実装は、効率的で正しいソリューションを提供します。 32 ビット アトミックを使用して 64 ビット アトミック カウンタを作成します。 SeqLock 設計により、カウンタがロックなしで動作することが保証され、データ競合を引き起こすことなく複数のリーダーと単一のライターが同時に動作できるようになります。
以上が32 ビット アトミックのみを使用して 64 ビット アトミック カウンターを実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。