如何正确使用std :: atomic_signal_fence()?

xml*_*lmx 11 c++ performance multithreading atomic c++11

cppreference.com将此函数记录为"在同一线程中执行的线程和信号处理程序之间的栅栏".但我在互联网上找不到任何例子.

我想知道以下伪代码是否正确地说明了以下函数std::atomic_signal_fence():

int n = 0;
SignalObject s;

void thread_1()
{
    s.wait();
    std::atomic_signal_fence(std::memory_order_acquire);
    assert(1 == n); // never fires ???
}

void thread_2()
{
    n = 1;
    s.signal();
}

int main()
{
    std::thread t1(thread_1);
    std::thread t2(thread_2);

    t1.join(); t2.join();
}
Run Code Online (Sandbox Code Playgroud)

bam*_*s53 19

不,您的代码没有证明正确使用atomic_signal_fence.当您引用cppreference.com时,atomic_signal_fence仅在信号处理程序和在同一线程上运行的其他代码之间执行同步.这意味着它不会在两个不同的线程之间执行同步.您的示例代码显示了两个不同的线程

C++规范包含有关此函数的以下注释:

注意:加载和存储的编译器优化和重新排序以与使用相同的方式被禁止atomic_thread_fence,但不会发出atomic_thread_fence将插入的硬件栅栏指令.

注意: atomic_signal_fence可用于指定线程执行的操作对信号处理程序可见的顺序.

以下是正确(如果不是激励)用法的示例:

static_assert(2 == ATOMIC_INT_LOCK_FREE, "this implementation does not guarantee that std::atomic<int> is always lock free.");

std::atomic<int> a = 0;
std::atomic<int> b = 0;

extern "C" void handler(int) {
    if (1 == a.load(std::memory_order_relaxed)) {
        std::atomic_signal_fence(std::memory_order_acquire);
        assert(1 == b.load(std::memory_order_relaxed));
    }

    std::exit(0);
}

int main() {
    std::signal(SIGTERM, &handler);

    b.store(1, std::memory_order_relaxed);
    std::atomic_signal_fence(std::memory_order_release);
    a.store(1, std::memory_order_relaxed);
}
Run Code Online (Sandbox Code Playgroud)

如果遇到断言,则保证保持为真.


小智 5

在您的示例中,您要使用std::atomic_thread_fence(生成机器代码以执行线程同步);not std::atomic_signal_fence(它只会禁用对原子变量的编译器内存重新排序优化)。正如其他人所说,std::atomic_signal_fence仅用于与原子操作相同线程上的信号(我相信它也适用于 Windows 上的结构化/向量化异常处理程序,但不要引用我的话)。