std::atomic::wait可以用来代替互斥体吗?

问题描述 投票:0回答:1

在阅读了问题 C++20 mutex withatomic wait 以及 有时可以使用 std::atomic 而不是 C++ 中的 std::mutex 吗?虽然类似,但我的疑问不同,我有这个疑问下面会解释一下:

我想知道调用 std::atomic::wait 函数来同步一段代码是否安全,正如许多人所建议的那样,似乎可以使用 std::atomic::wait,但我相信这也许并不完全安全,有发生死锁的风险

想象下面的代码:

#include <atomic>
#include <iostream>
#include <thread>
#include <vector>

std::atomic<bool> lock = false;

void go(){
    bool expected = false;
    while(!lock.compare_exchange_strong(expected, true)) {
        lock.wait(true);
        expected = false;
    }

    std::cout << "Sincronizado" << std::endl;

    lock = false;

    lock.notify_all();
}

int main() {
    std::vector<std::thread> threads;
    threads.reserve(2);

    for(int i = 0; i < 2; i++)
        threads.emplace_back(go);

    for(auto& thread : threads)
        thread.join();
}

到目前为止一切顺利,您可能已经在几个 Stackoverflow 问题中看到过它,但现在考虑以下场景:

主题 1:

+ 赢得比赛
while(!lock.compare_exchange_strong(expected, true))

+ 到达之前执行
lock = false;

的行 + 线程 1 被抢占

主题 2:

+ 输掉比赛
while(!lock.compare_exchange_strong(expected, true))

+ 开始执行该行
lock.wait(true);

+ 在线路内部(内部使用 Futex)它检查
if
锁定是否为真
+ 仍在行内,阻塞开始之前 (
FUTEX_WAIT
) 线程被抢占

主题 1:

+ 返回执行,并将lock设置为false。
+ 通知所有待处理线程
lock.notify_all();


主题 2:

+ 返回执行,阻塞开始(FUTEX_WAIT)
+ 可能会出现死锁吗?

这种情况可能发生还是我偏执了?

对于任何混乱,我深表歉意,我正在使用谷歌翻译,如果您有任何疑问,请使用评论。

等等!

如果我的问题不完整,或者格式不合适,请发表评论,以便我进行调整,提前谢谢您。

卢卡斯·P.

c++ multithreading synchronization mutex atomic
1个回答
0
投票

你的

compare_exchange_strong
循环是不必要的,
std::atomic::wait
已经为你做到了这一点:

执行原子等待操作。其行为就像重复执行以下步骤:

  • this->load(order)
    的值表示与
    old
    的值表示进行比较。
    • 如果它们相等,则阻塞,直到
      *this
      notify_one()
      通知
      notify_all()
      ,或者线程被虚假地解除阻塞。
    • 否则返回。

这些函数只有在值发生变化时才保证返回,即使底层实现虚假地解除阻塞。

wait
是原子的,所以最坏的情况下它会在你调用
notify
之前解锁,你永远不会像使用条件变量那样错过通知。

© www.soinside.com 2019 - 2024. All rights reserved.