C ++ std :: memory_order_relaxed和skip / stop标志

时间:2017-10-11 06:00:14

标签: c++ multithreading stdatomic memory-barriers

std::memory_order_relaxed用于跳过标记是否可以,例如iterate

    constexpr static const std::size_t capacity = 128; 
    std::atomic<bool> aliveness[capacity];
    T data[capacity];     // immutable/atomic/etc.

    template<class Closure>
    void iterate(Closure&& closure){
        for(std::size_t i = 0; i<capacity; i++){
            if (!aliveness[i].load(std::memory_order_relaxed)) continue;                    
            closure( data[i] );
        }
    }

    void erase(std::size_t index){
        aliveness[index].store(false, std::memory_order_relaxed);
    }

或者我应该使用发布/获取,而不是?

aliveness[i]可能变成&#34;活着&#34;试。

iterateerase同时从多个线程调用。在其他一些外部锁定下考虑data immutable / atomic / synchronized。

1 个答案:

答案 0 :(得分:4)

假设:当您使用iterate()时,其他线程可以随时erase运行。 (问题的早期版本没有指定不可变。如果更新data[i]的锁定(或缺少)不是有序的,那么这个答案仍然是相关的。写入alive[i] 。)

如果数据真的是不可变的,那么mo_relaxed绝对没问题,除非您需要针对线程正在做的事情 else 对这些商店的全局可见性进行排序。 mo_relaxed存储将始终最终对其他线程可见(并且在当前的CPU上,将非常快速地显示)。

如果您在data[i]为false时修改非原子alive[i],则需要确保其他线程在使用其值时不会使用其值{#1}}。被修改。那将是C ++中的UB,以及真实硬件上的实际正确性问题,具体取决于Tclosure

获取语义适用于iterate。在data[i]之后逻辑上可以访问alive[i],因为单向屏障的方向正确。 The acquire-load won't reorder with later loads or stores, only earlier ones

但是erase中的商店是个问题。在对data[i]进行任何修改之前,它必须是全局可见的。但是发布商店可以在以后的商店重新订购。你需要的是a release fence to block reordering of stores in both directions

void erase(std::size_t index){
    aliveness[index].store(false, std::memory_order_relaxed);
    std::atomic_thread_fence(std::memory_order_release);
}

如果T是原子类型,那么data[i]的发布商店就可以了。但是不要这样做;如果T太大而无法锁定原子,那将会很糟糕。

在大多数实现中,seq-cst存储也可以工作,但我认为仅作为实现细节。它通常会导致商店+全屏障asm指令。 (例如x86 MFENCE)。所以它的工作原理只是因为编译器将seq-cst存储实现为存储+ thread_fence(seq_cst)

请注意iterate如果closure修改data[],则void iterate(Closure&& closure) const { ... } 不安全,除非一次只有一个线程可以调用它。在这种情况下,这是什么意思?所以你应该使用

iterate

因此const仅适用于容器的Error: Hostname/IP doesn't match certificate's altnames: "Host: [s3bucket].s3.amazonaws.com. is not in the cert's altnames: DNS:[mydomain].com, DNS:www.[mydomain].com" 个对象。