You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于std::binary_semaphore的release()是否保证早于acquire()完成的疑问

疑问:std::binary_semaphore的release()是否保证早于配对的acquire()完成?

嘿,你的担心真的不是杞人忧天——多线程同步里的这些细节稍不注意就会出大问题,咱们结合你的代码来掰扯清楚这个事儿。

先把你的场景代码贴出来方便大家看:

class MyClass {
    std::binary_semaphore sem{0};
    std::binary_semaphore& sem(); // 内部返回sem的引用
    // 其他成员
};

void func1(MyClass& obj) {
    // 一些代码
    obj.sem().release();
}

void func2(MyClass& obj) {
    // 一些代码
    obj.sem().acquire();
    obj.~MyClass();
}

假设线程A在调用func1里的release(),线程B在调用func2里的acquire(),你怕的是会不会出现acquire()已经完成了,但release()还没彻底做完的情况?

放心,C++标准给std::binary_semaphore的操作做了明确的同步保证:

  • 当一个线程的release()操作使得信号量的计数从0变成1,另一个线程的acquire()因此成功返回时,release()的所有内存操作和副作用都在acquire()完成之前就已经结束了,而且标准定义了release()的完成是happens-beforeacquire()的完成的。简单说就是,只要acquire()成功拿到了信号量,那之前的release()肯定已经彻底做完了,不会有“半拉子”的情况。

不过这里还要提醒你一个代码里的小问题:func2里手动调用obj.~MyClass()是非常危险的操作,除非这个MyClass对象是用placement new在手动分配的内存上创建的。正常情况下,对象的析构应该由它的生命周期自动管理(比如栈对象出栈、智能指针自动释放),手动调用析构很容易导致重复析构、或者其他线程还在访问对象时就被析构的问题——哪怕这里的信号量同步没问题,手动析构本身就是个坑。

总结一下:你担心的release()和acquire()的顺序问题,标准已经给你兜底了,只要acquire()成功返回,release()肯定已经完成。但手动调用析构的操作一定要改,别给自己埋雷。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 13:40:31