原子操作と同時安全

1812 ワード

従来、原子操作と同時安全について誤解していたが、一つの操作が原子ではないと思っていたのは、同時安全ではないと考えていたので、それ以来、ためらっていた.
C言語の簡単な付与文も原子ではありませんか?a=bは原子操作ですか?コードは次のとおりです.

int main() {
    int a = 0;
    int b = 2;
    a = b;
}

このコードをコンパイルする:g++-c-g-Wa,-adlhn Assign.c > Assign.asm
(a=b部分asmコードのみを表示):

movl	-8(%ebp), %eax
movl	%eax, -4(%ebp)

2つのアセンブリ命令で操作が完了し、簡単に説明します.
  • a ==> -4(%ebp)
  • b ==> -8(%ebp)
  • movlはmovパラメータの順序とは逆であり、movl SRC、DEST
  • movl-8(%ebp),%eax=>movl b,%eax(レジスタ%eaxをbに割り当てた値)
  • movl%eax,-4(%ebp)=>movl%eax,a(aの値をレジスタ%eaxの値に割り当てる)
  • この2つの命令により,最終的にa=bの付与が実現された.
    だから、a=bは原子ではないと責任を持って言えるようです.
    原子ではない以上、同時に安全なのではないでしょうか.もちろん、上記の例は合併とはあまり関係ないようですが、このようなクラスを定義しましょう.
    
    class CObject {
    private:
        int _v;
    public:
        CObject() { _v = 0; }
        void putValue(int v) { _v = v; }
        int  getValue() const { return _v; }
    };
    

    同じようにただ見るだけですv=v部のアセンブル命令
    
    movl	8(%ebp), %eax
    movl	12(%ebp), %edx
    movl	%edx, (%eax)
    

    次のように解釈されます.
  • 8(%ebp) ==> _v
  • 12(%ebp) ==> v
  • movl 8(%ebp),%eax=>%eax賦値_vのアドレス
  • movl 12(%ebp),%edx=>%edxはvのアドレス
  • に割り当てられる
  • movl%edx,(%eax)=>%eax対応アドレスの値は%edx対応値
  • として付与.
    過程は実はすべて同じで、説明のために、付与操作は原子ではありません.
    もし私の以前の理解であれば、原子操作でなければ同時安全ではありません.同時プログラムはどう書きますか.
    実は、これは私の誤解だとしか言えません.まず、どのような状況で同時問題が発生するかをよく考えてみましょう.私の理解では、複数のスレッドがデータを共有することを競争しているときに、同時問題が発生します.振り返ってみると、上のいくつかの行のアセンブリコードを見てみましょう.vは共有データに属し、本当に競争を生み出すことができるのはmovl%edx,(%eax)だけで、この時、複数のスレッドがこのステップの操作をしたいかもしれませんが、実際にはこの操作は原子であるべきでしょう.そのため、このような付与操作は同時安全であるべきです.