【问题标题】:call_once implementation through double checked locking pattern通过双重检查锁定模式实现 call_once
【发布时间】:2013-08-22 19:18:29
【问题描述】:

boost::call_once 是如何实现的?

这是否使用双重检查锁定模式?

Qt 或 POCO 库中是否有任何等效的实现?

【问题讨论】:

  • 你知道'双重检查锁定模式'不好?
  • 我不会 POCO 线程
  • 问题是我需要在多线程环境中实现单例模式。我对双重检查锁定模式(及其低效率)和 boost call_once 做了一些分析。我不应该使用 boost 库。所以我需要一个实现。
  • 我的编译器不支持 std::call_once。
  • 静态单例实例 - 在 main 之前?

标签: c++ qt boost poco-libraries


【解决方案1】:

我偶然发现了这个较老的问题.. 4 年后,您的案例可能不再感兴趣,但我相信示例实现可能仍有一些价值。

与 cmets 部分中声称 DCLP 已损坏的说法相反,这在 C++11 中不再适用,因为它提供了必要的原子类型、操作和内存屏障。

这是一个最小的实现,不一定是boost 实现。异常行为被忽略。
my_call_once 的参数函数保证被调用不超过一次,并且共享数据在线程之间正确同步.. 就像真实的 std::call_once 一样

#include <iostream>
#include <thread>
#include <mutex>
#include <atomic>

class my_once_flag {
    std::mutex mtx;
    std::atomic<bool> flg{false};

    template<typename Func, typename... Args>
    friend void my_call_once(my_once_flag&, Func&&, Args&&...);
};

template<typename Func, typename... Args>
void my_call_once(my_once_flag& flag, Func&& f, Args&&... args)
{
    if (flag.flg.load(std::memory_order_acquire) == false)
    {
        std::lock_guard<std::mutex> lck{flag.mtx};

        if (flag.flg.load(std::memory_order_relaxed) == true)
            return;

        std::forward<Func>(f)(std::forward<Args>(args)...);

        flag.flg.store(true, std::memory_order_release);
    }
}

void just_once(int i) { std::cout << "once " << i << std::endl; }

int main()
{
    my_once_flag of;

    std::thread {[&]{ my_call_once(of, just_once, 1); }}.join();
    std::thread {[&]{ my_call_once(of, just_once, 2); }}.join();
}

【讨论】:

    猜你喜欢
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多