1

考虑 GCC 4.8.0 下的这段代码:

std::atomic<bool> a;
std::atomic<bool> b;

a.store( b.load() ); // want to be atomic

我怎样才能使上面的行整体是原子的?换句话说,如何获得原子变量的原子赋值?

是否有任何替代方案std::atomic允许这样做?


我发现__transaction_atomic {/* any code goes here */}哪个在 GCC 上由-fgnu-tm. 有了这个,人们可以在块中写任何东西,并且它将被原子地执行。

现在的问题是:

__transaction_atomic用互斥锁实现的吗?如果是,那么互斥锁实际上锁定了什么?

更改的实施是否__transaction_atomic取决于其块中的内容?如果是,那么它是如何变化的?

4

2 回答 2

3

我不认为这是可能的。我认为进行这样的操作没有用处。你为什么需要它?如果您有如此严格的要求,那么您应该只使用std::mutex锁定a = b分配。

更新

我已经__transaction_atomic用 Cygwin64 的 GCC 4.8.1 和这个非常短的源测试了这个块

extern int a, b;

void foo ()
{ 
    __transaction_atomic
    {
        a = b;
    }
}

导致大量指令调用 ITM 库函数

_Z3foov:
.LFB0:
    pushq   %rdi     #
    .seh_pushreg    %rdi
    pushq   %rsi     #
    .seh_pushreg    %rsi
    subq    $200, %rsp   #,
    .seh_stackalloc 200
    movaps  %xmm6, 32(%rsp)  #,
    .seh_savexmm    %xmm6, 32
    movaps  %xmm7, 48(%rsp)  #,
    .seh_savexmm    %xmm7, 48
    movaps  %xmm8, 64(%rsp)  #,
    .seh_savexmm    %xmm8, 64
    movaps  %xmm9, 80(%rsp)  #,
    .seh_savexmm    %xmm9, 80
    movaps  %xmm10, 96(%rsp)     #,
    .seh_savexmm    %xmm10, 96
    movaps  %xmm11, 112(%rsp)    #,
    .seh_savexmm    %xmm11, 112
    movaps  %xmm12, 128(%rsp)    #,
    .seh_savexmm    %xmm12, 128
    movaps  %xmm13, 144(%rsp)    #,
    .seh_savexmm    %xmm13, 144
    movaps  %xmm14, 160(%rsp)    #,
    .seh_savexmm    %xmm14, 160
    movaps  %xmm15, 176(%rsp)    #,
    .seh_savexmm    %xmm15, 176
    .seh_endprologue
    movl    $43, %edi    #,
    xorl    %eax, %eax   #
    call    _ITM_beginTransaction    #
    testb   $2, %al  #, tm_state.4
    je  .L2  #,
    movq    .refptr.b(%rip), %rax    #, tmp67
    movl    (%rax), %edx     # b, b
    movq    .refptr.a(%rip), %rax    #, tmp66
    movl    %edx, (%rax)     # b, a
    movaps  32(%rsp), %xmm6  #,
    movaps  48(%rsp), %xmm7  #,
    movaps  64(%rsp), %xmm8  #,
    movaps  80(%rsp), %xmm9  #,
    movaps  96(%rsp), %xmm10     #,
    movaps  112(%rsp), %xmm11    #,
    movaps  128(%rsp), %xmm12    #,
    movaps  144(%rsp), %xmm13    #,
    movaps  160(%rsp), %xmm14    #,
    movaps  176(%rsp), %xmm15    #,
    addq    $200, %rsp   #,
    popq    %rsi     #
    popq    %rdi     #
    jmp _ITM_commitTransaction   #
    .p2align 4,,10
.L2:
    movq    .refptr.b(%rip), %rcx    #,
    call    _ITM_RU4     #
    movq    .refptr.a(%rip), %rcx    #,
    movl    %eax, %edx   # D.2368,
    call    _ITM_WU4     #
    call    _ITM_commitTransaction   #
    nop
    movaps  32(%rsp), %xmm6  #,
    movaps  48(%rsp), %xmm7  #,
    movaps  64(%rsp), %xmm8  #,
    movaps  80(%rsp), %xmm9  #,
    movaps  96(%rsp), %xmm10     #,
    movaps  112(%rsp), %xmm11    #,
    movaps  128(%rsp), %xmm12    #,
    movaps  144(%rsp), %xmm13    #,
    movaps  160(%rsp), %xmm14    #,
    movaps  176(%rsp), %xmm15    #,
    addq    $200, %rsp   #,
    popq    %rsi     #
    popq    %rdi     #
    ret
    .seh_endproc
    .ident  "GCC: (GNU) 4.8.1"
    .def    _ITM_beginTransaction;  .scl    2;  .type   32; .endef
    .def    _ITM_commitTransaction; .scl    2;  .type   32; .endef
    .def    _ITM_RU4;   .scl    2;  .type   32; .endef
    .def    _ITM_WU4;   .scl    2;  .type   32; .endef
    .section    .rdata$.refptr.b, "dr"
    .globl  .refptr.b
    .linkonce   discard
.refptr.b:
    .quad   b
    .section    .rdata$.refptr.a, "dr"
    .globl  .refptr.a
    .linkonce   discard
.refptr.a:
    .quad   a

这是有-O3选择的。

于 2013-07-28T21:19:19.357 回答
2

理论上,原子变量交换可以在几个支持DCAS的 CPU 上实现。实际上,没有现代 CPU 支持 DCAS,因此这是不可能的。

于 2013-07-28T21:44:33.360 回答