はい、x86 ではいくつかの選択肢があります。
XADD r/m, r
この命令は、第 2 オペランド (r) を第 1 オペランド (r/m) に原子的に追加し、第 2 オペランド (r) に第 1 オペランド (r/m) の元の値をロードします。
それを使用するには、2 番目のオペランドにインクリメントの量 (ここでは 1 と推測しています) をロードする必要があります。
この命令の前に LOCK プレフィックスを付ける必要があります (これによりアトミックになります)。
Microsoft Visual C++のInterlockedAdd()
関数はこれを行い、AFAIR がXADD
利用可能な場合は使用します (i80486 以降で利用可能)。
別の方法は、命令でループを使用することCMPXCHG
です...
擬似コード:
while (true)
{
int oldValue = l.n;
int newValue = oldValue + 1;
if (CAS(&l.n, newValue, oldValue) == oldValue)
break;
}
(並行プログラミングの一般的な用語)CAS()
を表す はCompare And Swap
、メモリ内の値を新しい値にアトミックに置き換えようとする関数です。置換される値が最後に指定されたパラメーターと等しい場合、置換は成功しますoldValue
。それ以外の場合は失敗します。CAS
はメモリから元の値を返します。これにより、置換が成功したかどうかがわかります (返された値を と比較しますoldValue
)。失敗 (返された元の値は とは異なりますoldValue
) は、読み取りと、それを別のスレッドoldValue
に置き換えようとした瞬間との間に、メモリ内の値が変更されたことを示しています。newValue
この場合、手順全体を再試行するだけです。
命令はCMPXCHG
x86CAS
です。
Microsoft Visual C++InterlockedCompareExchange()
ではCMPXCHG
、CAS
.
XADD
利用できない場合は、 //InterlockedAdd()
を使用して実装されます。CAS
CMPXCHG
InterlockedCompareExchange()
他の一部の CPU では、別の可能性があります。隣接するいくつかの命令をアトミックに実行できるものもあります。