c++ - 使用 std::shared_ptr/weak_ptr 简化观察者模式

标签 c++ concurrency

这是一个简化的观察者模式:

  • 一个创建者在开始时创建一个配置文件,并在完成后“销毁”它。
  • 零,一个或多个观察者随时尝试“查看”轮廓。

  • 要实现它,诀窍是观察者应该 refcnt 配置文件,所以最后一个观察者(或创建者)可以安全地销毁它。
    我可以在没有 shared_ptr/weak_ptr 的情况下做到这一点,但我想知道使用它们是否可以避免重新发明轮子。
    这是我的代码:
    #include <iostream>
    #include <memory>
    #include <thread>
    #include <cassert>
    
    volatile bool playing = true;
    
    class Profile {
    public:
        int a_;
        Profile(int v) {a_ = v;}
    };
    
    std::shared_ptr<Profile> g_profile{ nullptr };
    
    void observer() {
        do {
            // observe profile if I can
            std::weak_ptr<Profile> weak = g_profile;
            if (auto prof = weak.lock()) {
                auto a = prof->a_;
                // if prof is stable, I shall see the same a_
                assert(a == prof->a_);
            }
            else {
                std::cout << ".";
            }
        } while (playing);
    }
    
    void creator() {
        do {
            // create profile when I start
            g_profile.reset(new Profile(std::rand()));
            std::weak_ptr<Profile> weak = g_profile;
            assert(weak.lock() != nullptr);
            
            // doing some work ...
    
            // destroy profile when I am done
            g_profile.reset();
        } while (playing);
    }
    
    void timer() {
        std::this_thread::sleep_for(std::chrono::seconds(10));
        playing = false;
    }
    
    int main() {
        std::thread cr{ creator };
        std::thread ob{ observer };
        std::thread tm{ timer };
        cr.join();ob.join();tm.join();
    
        // no memory leak
    }
    
    但是程序在std::weak_ptr<Profile> weak = g_profileassert(a == prof->a_) .所以这里是我的问题:
  • 你有一个指针,用 shared_ptr/weak_ptr 实现观察者模式(或变体)吗?
  • 上面的代码有什么问题?你能做对吗?
  • 最佳答案

    您有 undefined bahavior当一个线程读取共享指针时 g_profile (观察者)而另一个线程写入它(当创建者调用 std::shared_ptr::reset 时)
    如果您想使用 shared_ptr从两个线程你必须使用锁或 atomic_shared_ptr .
    还有 volatile不保证任何同步,因为它在 java 中。见 this answer .

    关于c++ - 使用 std::shared_ptr/weak_ptr 简化观察者模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63025270/

    相关文章:

    c++ - 预处理器定义不会从 CMake 传播到 Unix Makefile

    java - 停放正在使用的线程

    c# - 退出没有循环的线程

    c++ - 为什么 pthread_key_create 析构函数被调用了几次?

    c - 生产者、消费者 POSIX

    c++ - 资助 MathML 渲染库

    c++ - 关于输入参数的顺序

    c++ - Qt StyleSheet 以编程方式创建QWidget

    c++ - 探查器输出中线程并发开销时间的含义是什么?

    java - 如何测试一个线程是否是 Java 中唯一剩余的线程?