0
点赞
收藏
分享

微信扫一扫

什么是外贸专用路由器?

月半小夜曲_ 2024-09-14 阅读 25
c++服务器

目录

类的线程安全

实现线程安全 

构造函数在多线程中的安全性

析构函数多线程环境的安全

智能指针实现多线程安全

 shared_ptr 非完全线程安全

shared_ptr可能导致对象生命周期延长

const引用可以减少传递shared_ptr开销

shared_ptr 智能指针块模块的优点

 析构所在线程问题分析

 RAII的使用

enable_shared_from_this 使用场景分析

问题分析

enable_shared_from_this确保对象安全

 weak_ptr 和 shared_ptr 结合 Bind的弱回调机制(重点解决方案)

弱回调机制的实现


类的线程安全

实现线程安全 

构造函数在多线程中的安全性

#include <iostream>

class Observable;

class Observer {
public:
    virtual void update() = 0;  // 纯虚函数,用于接收更新通知
};

class Foo : public Observer {
public:
    // 错误:在构造函数中直接注册 `this`,会造成线程不安全
    Foo(Observable* s) {
        s->registerObserver(this);  // 将 `this` 立即注册到 `Observable`
        std::cout << "Foo 对象已构造并注册\n";
    }

    virtual void update() override {
        std::cout << "Foo 收到了更新通知\n";
    }

private:
    int someData = 0;  // 假设这是一个重要的初始化数据
};

class Observable {
public:
    void registerObserver(Observer* o) {
        observer_ = o;
        std::cout << "观察者已注册\n";
    }

    void notifyObservers() {
        if (observer_) {
            observer_->update();
        }
    }

private:
    Observer* observer_ = nullptr;
};

int main() {
    Observable observable;
    Foo* foo = new Foo(&observable);  // 在构造函数中注册 `this`
    
    observable.notifyObservers();  // 通知观察者,可能在对象未完全初始化时访问

    delete foo;
    return 0;
}
#include <iostream>

class Observable;

class Observer {
public:
    virtual void update() = 0;  // 纯虚函数,用于接收更新通知
};

class Foo : public Observer {
public:
    Foo() {
        // 在构造函数中仅初始化对象,不进行任何注册操作
        std::cout << "Foo 对象已构造\n";
    }

    // 观察者更新接口实现
    virtual void update() override {
        std::cout << "Foo 收到了更新通知\n";
    }

    // 提供一个专门的函数用于在构造后进行注册
    void observe(Observable* s);

private:
    // 内部成员变量
    int someData = 0;
};

class Observable {
public:
    void registerObserver(Observer* o) {
        observer_ = o;
        std::cout << "观察者已注册\n";
    }

    void notifyObservers() {
        if (observer_) {
            observer_->update();
        }
    }

private:
    Observer* observer_ = nullptr;
};

// Foo类的observe方法实现,确保注册操作在构造完成后进行
void Foo::observe(Observable* s) {
    s->registerObserver(this);  // 仅在对象构造后再注册
}

int main() {
    Observable observable;
    Foo* foo = new Foo();  // 构造对象
    
    foo->observe(&observable);  // 构造完成后进行注册
    observable.notifyObservers();  // 通知观察者进行更新

    delete foo;
    return 0;
}

析构函数多线程环境的安全

多线程环境下的析构比单线程析构是更为复杂的,主要原因是因为其涉及到资源的竞争条件。如果在多线程环境下确保线程安全,析构函数必须小心处理对象的状态,同时与其他线程保持同步。

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

class Foo {
public:
    ~Foo() {
        std::lock_guard<std::mutex> lock(mutex_);  // 互斥锁保护析构函数
        std::cout << "Foo 被销毁\n";
    }

    void update() {
        std::lock_guard<std::mutex> lock(mutex_);  // 互斥锁保护更新函数
        std::cout << "Foo 更新\n";
    }

private:
    std::mutex mutex_;
};

Foo* x = nullptr;  // 全局对象指针,多个线程共享

void threadA() {
    delete x;      // 线程A销毁对象
    x = nullptr;   // 设置 x 为 NULL
}

void threadB() {
    if (x) {       // 线程B检查 x 是否为NULL
        x->update();  // 如果 x 不为NULL,则调用 update()
    } else {
        std::cout << "x 是空指针\n";
    }
}

int main() {
    x = new Foo();  // 初始化全局对象指针

    std::thread t1(threadA);  // 线程A销毁对象
    std::thread t2(threadB);  // 线程B调用 update()

    t1.join();
    t2.join();

    return 0;
}

 ​​​​​

智能指针实现多线程安全

#include <iostream>
#include <memory>
#include <thread>

std::shared_ptr<int> globalPtr;  // 全局 shared_ptr

void threadFunc() {
    std::shared_ptr<int> localPtr = globalPtr;  // 安全地共享对象
    if (localPtr) {
        std::cout << "Thread accessing: " << *localPtr << std::endl;
    }
}

int main() {
    globalPtr = std::make_shared<int>(42);  // 初始化 shared_ptr

    std::thread t1(threadFunc);
    std::thread t2(threadFunc);

    t1.join();
    t2.join();

    globalPtr.reset();  // 主线程释放对象,其他线程仍然安全使用

    return 0;
}

 shared_ptr 非完全线程安全

#include <iostream>
#include <memory>
#include <thread>
#include <mutex>

std::shared_ptr<int> globalPtr;
std::mutex mtx;

void readSharedPtr() {
    std::lock_guard<std::mutex> lock(mtx);
    if (globalPtr) {
        std::cout << "Reading: " << *globalPtr << std::endl;
    }
}

void writeSharedPtr(int value) {
    std::lock_guard<std::mutex> lock(mtx);
    if (globalPtr) {
        *globalPtr = value;
        std::cout << "Writing: " << value << std::endl;
    }
}

int main() {
    globalPtr = std::make_shared<int>(42);

    std::thread t1(readSharedPtr);
    std::thread t2(writeSharedPtr, 100);

    t1.join();
    t2.join();

    return 0;
}

shared_ptr可能导致对象生命周期延长

shared_ptr是引用计数的智能指针,引用计数决定的对象的生命周期,但是使用过程中如果有一个指向该对象的指针没有析构,这样就会导致该对象永远不会被释放。

#define BOOST_BIND_GLOBAL_PLACEHOLDERS 
#include <iostream>
#include <vector>
#include <memory>
#include <boost/bind.hpp>
#include <boost/function.hpp>

class Observer {
public:
    Observer(int id) : id_(id) {
        std::cout << "Observer " << id_ << " created." << std::endl;
    }
    ~Observer() {
        std::cout << "Observer " << id_ << " destroyed." << std::endl;
    }

    void onNotify() {
        std::cout << "Observer " << id_ << " notified." << std::endl;
    }

private:
    int id_;
};

class Subject {
public:
    void registerObserver(std::shared_ptr<Observer> obs) {
        observers_.push_back(obs);  // 使用 shared_ptr 存储观察者
    }

    void unregisterObserver(std::shared_ptr<Observer> obs) {
        observers_.erase(std::remove(observers_.begin(), observers_.end(), obs), observers_.end());
    }

    void notifyAll() {
        for (auto& obs : observers_) {
            if (obs) {
                obs->onNotify();
            }
        }
    }

private:
    std::vector<std::shared_ptr<Observer>> observers_;
};

void delayedCallback(boost::function<void()> func) {
    std::cout << "Callback will be called after delay..." << std::endl;
    func();  // 延迟回调调用
}

int main() {
    Subject subject;
    
    // 创建两个观察者并注册
    std::shared_ptr<Observer> observer1(new Observer(1));
    std::shared_ptr<Observer> observer2(new Observer(2));
    
    subject.registerObserver(observer1);
    subject.registerObserver(observer2);
    
    // 这里的 boost::bind 使 shared_ptr 的引用计数增加
    boost::function<void()> func = boost::bind(&Observer::onNotify, observer1);
    
    // 执行延迟回调
    delayedCallback(func);
    
    // 移除观察者
    subject.unregisterObserver(observer1);
    subject.unregisterObserver(observer2);

    // 通知所有观察者
    subject.notifyAll();

    // 注意:observer1 的引用计数不会为 0,因为 boost::function 持有了它的 shared_ptr 副本
    return 0;
}

 

const引用可以减少传递shared_ptr开销

void onMessage(const std::string& msg) {
    std::shared_ptr<Foo> pFoo(new Foo(msg));  // 创建 shared_ptr,持有 Foo 实例

    if (validate(pFoo)) {  // 通过 const 引用传递 shared_ptr
        save(pFoo);        // 通过 const 引用传递 shared_ptr
    }
}

shared_ptr 智能指针块模块的优点

 析构所在线程问题分析

在多线程环境下,最后拥有对象的线程不一定是初始线程,所以需要该处对最后析构线程进行分析。

 RAII的使用

涉及到资源管理必然不可以绕开RAII,RAII的核心思想就是在对象构建的时候同时获取资源,并在对象销毁的时候同时释放资源。

#include <iostream>
#include <memory>
#include <thread>
#include <chrono>
#include <queue>
#include <mutex>
#include <condition_variable>

// 资源类,构造时分配资源,析构时释放资源
class Resource {
public:
    Resource() {
        std::cout << "资源已获取\n";
    }
    ~Resource() {
        std::cout << "资源已释放\n";
    }
};

// 模拟处理资源的函数
void processResource(std::shared_ptr<Resource> res) {
    std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟处理延迟
    std::cout << "正在处理资源\n";
}

// 阻塞队列类,用于在线程间传递资源
template <typename T>
class BlockingQueue {
public:
    // 向队列中添加资源
    void push(T item) {
        std::lock_guard<std::mutex> lock(mtx);
        queue.push(item);
        cond.notify_one(); // 唤醒等待的线程
    }

    // 从队列中取出资源
    T pop() {
        std::unique_lock<std::mutex> lock(mtx);
        cond.wait(lock, [this]() { return !queue.empty(); }); // 等待直到队列非空
        T item = queue.front();
        queue.pop();
        return item;
    }

private:
    std::queue<T> queue;
    std::mutex mtx;
    std::condition_variable cond;
};

// 专用线程,处理资源的析构
void workerThread(BlockingQueue<std::shared_ptr<Resource>>& queue) {
    while (true) {
        auto res = queue.pop(); // 从队列中获取资源
        processResource(res);   // 处理资源
        // 资源会在这里自动析构
    }
}

int main() {
    // 创建阻塞队列和专用线程
    BlockingQueue<std::shared_ptr<Resource>> queue;
    std::thread worker(workerThread, std::ref(queue));

    // 主线程分配资源并将其传递给专用线程
    {
        auto res = std::make_shared<Resource>(); // 使用shared_ptr分配资源
        queue.push(res); // 将资源传递给队列,worker线程将接管资源
    }

    worker.join(); // 等待专用线程结束
    return 0;
}

enable_shared_from_this 使用场景分析

问题分析

当使用智能指针来管理对象的生命周期,智能指针会自动管理对象资源的分配和释放,从而避免内存泄漏。但是在某些情况下,智能指针所管理的对象需要在其成员函数内存获取一个指向自身的shared_ptr。在这种情况下如果直接使用this指针操作,可能会导致严重的生命周期管理的问题,尤其在回调函数以及多线程环境下,该问题会更明显,结合下面的事例详细理解。

#include <iostream>
#include <memory>
#include <functional>

class Manager : public std::enable_shared_from_this<Manager> {
public:
    // 模拟删除资源的函数
    void deleteResource() {
        std::cout << "Manager: Deleting resource\n";
    }

    // 返回当前对象的shared_ptr
    std::shared_ptr<Manager> getSharedManager() {
        return shared_from_this();
    }
};

class Resource {
public:
    Resource(std::shared_ptr<Manager> mgr) : manager(mgr) {
        std::cout << "Resource Created\n";
        // 绑定析构时的回调函数,调用Manager的deleteResource函数
        destructorCallback = std::bind(&Manager::deleteResource, manager);
    }

    ~Resource() {
        std::cout << "Resource Destroyed\n";
        // 调用析构回调,通知Manager
        destructorCallback();
    }

private:
    std::shared_ptr<Manager> manager;
    std::function<void()> destructorCallback;
};

int main() {
    // 创建一个Manager对象并使用shared_ptr管理其生命周期
    std::shared_ptr<Manager> manager = std::make_shared<Manager>();

    {
        // 创建Resource对象,并将Manager传递给它
        std::shared_ptr<Resource> resource = std::make_shared<Resource>(manager);
    } // Resource在此作用域结束时被销毁,其析构函数被调用

    std::cout << "End of main\n";
    return 0;
}

enable_shared_from_this确保对象安全

解决上述问题,则是通过C++中提供的一个enable_shared_from_this机制来实现,其是一个模版基类,允许类的实例从其成员函数中安全的获取shared_ptr执行自身,最终实现该对象的生命周期始终是由shared_ptr来控制的。

#include <iostream>
#include <memory>

class Manager : public std::enable_shared_from_this<Manager> {
public:
    Manager() {
        std::cout << "Manager Created\n";
    }
    
    ~Manager() {
        std::cout << "Manager Destroyed\n";
    }

    // 返回自身的 shared_ptr
    std::shared_ptr<Manager> getSharedPtr() {
        return shared_from_this();
    }

    void performTask() {
        // 在成员函数内部获取 shared_ptr
        auto sharedManager = shared_from_this();
        std::cout << "Performing task with shared_ptr\n";
        // 在这里 shared_ptr 的引用计数不会变成 0,因为还有其他地方持有它
    }
};

int main() {
    // Step 1: 创建一个 shared_ptr 管理 Manager 对象
    std::shared_ptr<Manager> manager1 = std::make_shared<Manager>();
    std::cout << "Reference Count after creation: " << manager1.use_count() << "\n"; // 引用计数为 1

    // Step 2: 调用成员函数,获取 shared_ptr
    manager1->performTask();
    std::cout << "Reference Count after performTask: " << manager1.use_count() << "\n"; // 引用计数为 1,因为没有新增外部持有者

    // Step 3: 在外部再获取一个 shared_ptr
    std::shared_ptr<Manager> manager2 = manager1->getSharedPtr();
    std::cout << "Reference Count after getSharedPtr: " << manager1.use_count() << "\n"; // 引用计数为 2

    // Step 4: 销毁 manager1
    manager1.reset(); 
    std::cout << "Reference Count after resetting manager1: " << manager2.use_count() << "\n"; // 引用计数为 1

    // Step 5: 销毁 manager2
    manager2.reset();
    std::cout << "All shared_ptrs destroyed\n";

    return 0;
}

 weak_ptr 和 shared_ptr 结合 Bind的弱回调机制(重点解决方案)

弱回调机制的实现

 

 

 

#include <iostream>
#include <memory>
#include <vector>

// 前置声明 Manager 类
class Manager;

// Worker 类负责执行任务,并在任务完成时通知 Manager
class Worker {
public:
    // 构造函数中传入 Manager 的 weak_ptr
    Worker(std::weak_ptr<Manager> manager);

    ~Worker();

    // 执行任务
    void doWork();

private:
    // 使用 weak_ptr 避免循环引用
    std::weak_ptr<Manager> manager_;

    // 通知 Manager 任务已完成
    void notifyManager();
};

// Manager 类负责管理 Worker
class Manager : public std::enable_shared_from_this<Manager> {
public:
    Manager() {
        std::cout << "Manager Created\n";
    }
    
    ~Manager() {
        std::cout << "Manager Destroyed\n";
    }

    // 注册 worker 完成任务的回调函数
    void registerWorker() {
        auto worker = std::make_shared<Worker>(shared_from_this());
        workers_.push_back(worker);
        worker->doWork();
    }

    void onTaskComplete() {
        std::cout << "Manager received task completion notification\n";
    }

private:
    std::vector<std::shared_ptr<Worker>> workers_;
};

// 完整定义 Worker 类的方法
Worker::Worker(std::weak_ptr<Manager> manager)
    : manager_(manager) {
    std::cout << "Worker Created\n";
}

Worker::~Worker() {
    std::cout << "Worker Destroyed\n";
}

void Worker::doWork() {
    std::cout << "Worker is working...\n";
    
    // 模拟任务完成后通知 Manager
    notifyManager();
}

void Worker::notifyManager() {
    if (auto manager = manager_.lock()) {
        // manager 有效时通知
        manager->onTaskComplete();
    } else {
        // 如果 Manager 已销毁,通知失败
        std::cout << "Manager is no longer available\n";
    }
}

int main() {
    {
        // 创建一个 Manager 对象并用 shared_ptr 管理
        auto manager = std::make_shared<Manager>();
        
        // 注册 Worker 并执行任务
        manager->registerWorker();
        
        std::cout << "Manager still exists\n";
    }

    // 当 Manager 销毁后,Worker 再次尝试访问 Manager 将失败
    std::cout << "End of main\n";
    return 0;
}
举报

相关推荐

0 条评论