繁体   English   中英

使用无锁算法阻止并发队列

[英]Blocking concurrent queue with lock-free algorithms

我正在建立一个阻塞的并发队列(即,如果队列中什么都没有,那么消费者就会睡觉,直到生产者将其唤醒)。 我的用例受到限制,因为出队操作将始终在空队列上阻塞; 没有tryDequeue

我当前的实现仅使用带有std::condition_variablestd::mutex 我想知道使用无锁算法来改善数据结构是否有意义。 在队列为空的情况下,这可能没有任何意义,因为消费者无论如何都要阻塞。 但是在队列为非空的情况下,我能做些什么吗?

我认为这个问题正在询问您是否应该解除锁定。

在现代系统上,仅当每个项目的工作时间基本上在1毫秒以下或某些热闹的大规模锁争用情况下(未讨论,Web服务器是一个示例),无锁才有意义。

通过查看条件变量的响应时间,您可以感觉到通知条件变量的时间:

#include <thread>
#include <array>
#include <mutex>
#include <iostream>
#include <condition_variable>

std::chrono::microseconds timestamp()
{
    const auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
    return microseconds;
}
struct measurement
{
    std::chrono::microseconds sent, acknowledged, received;
    measurement() :sent{ 0 }, acknowledged{ 0 }, received{ 0 } {}
};

int main(int argc, char** argv)
{
    std::array<measurement, 15> notifications;
    std::mutex notifications_m;
    std::condition_variable notification_cv;
    auto notifying_thread = std::thread([&] {
        for (auto i = 0; i < notifications.size(); ++i)
        {
            {
                std::unique_lock<std::mutex> lk(notifications_m);
                notifications[i].sent = timestamp();
            }
            notification_cv.notify_one();
            //Now we wait for the notification to be acknowledged
            std::unique_lock<std::mutex> lk(notifications_m);
            const auto check_that_acknowledged = [&] {return notifications[i].acknowledged != std::chrono::microseconds(0); };
            notification_cv.wait(lk, check_that_acknowledged);
            notifications[i].received = timestamp();

        }
    });
    for (auto i = 0; i < notifications.size(); ++i)
    {
        {
            std::unique_lock<std::mutex> lk(notifications_m);
            const auto check_that_sent = [&] {return notifications[i].sent != std::chrono::microseconds(0); };
            notification_cv.wait(lk, check_that_sent);
            notifications[i].acknowledged = timestamp();
        }
        notification_cv.notify_one();
    }
    notifying_thread.join();
    //
    for (const auto& notification : notifications)
    {
        const auto difference_us = notification.received - notification.sent;
        std::cout << difference_us.count() << " microseconds" << std::endl;
    }
    return 0;
}

即使在某些延迟最高的系统上,往返也需要约0.1毫秒: https//coliru.stacked-crooked.com/a/9598c83dd05e09b5

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM