首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ 全局變量變化監控方案:多線程輪詢 vs 設計模式最佳實踐

     編輯:程式設計疑難解答

問題本質

需求:全局變量發生變化時,自動觸發類方法調用。本質是觀察者模式在全局狀態上的應用。

方案對比評估

方案實現複雜度實時性資源消耗線程安全推薦度
多線程輪詢低延遲 = 輪詢間隔持續佔用 CPU需鎖保護⭐
封裝 Setter + 回調低即時極低需鎖/原子操作⭐⭐⭐⭐
觀察者模式中即時低線程安全容器⭐⭐⭐⭐⭐
信號量/條件變量中即時低(阻塞等待)系統級同步⭐⭐⭐
屬性監聽框架高即時框架開銷框架保證⭐⭐⭐

推薦方案一:封裝全局變量 + 註冊回調(輕量、實用)


class GlobalConfig {
    int value;
    std::mutex mtx;
    std::vector> callbacks;

public:
    int get() { 
        std::lock_guard lock(mtx); 
        return value; 
    }

    void set(int newVal) {
        std::lock_guard lock(mtx);
        if (value != newVal) {
            value = newVal;
            // 複製回調列表,避免回調中修改容器導致死鎖
            auto cbs = callbacks;
        }
        for (auto &cb : cbs) cb(value);
    }

    void registerCallback(std::function cb) {
        std::lock_guard lock(mtx);
        callbacks.push_back(cb);
    }
};

// 全局實例
GlobalConfig g_config;

// 使用者類
class MyClass {
public:
    MyClass() {
        g_config.registerCallback([this](int v) { onConfigChanged(v); });
    }
    void onConfigChanged(int v) { /* 處理變化 */ }
};

推薦方案二:標準觀察者模式(擴展性強)


// 抽象主題
class Subject {
    std::vector observers;
    std::mutex mtx;
public:
    void attach(Observer* o) { 
        std::lock_guard lock(mtx); 
        observers.push_back(o); 
    }
    void detach(Observer* o) { ... }
    void notify(int value) {
        std::lock_guard lock(mtx);
        for (auto o : observers) o->update(value);
    }
};

// 具體主題:全局配置
class GlobalConfig : public Subject {
    int value;
public:
    void setValue(int v) {
        if (value != v) {
            value = v;
            notify(value);
        }
    }
    int getValue() const { return value; }
};

// 觀察者接口
class Observer {
public:
    virtual void update(int value) = 0;
    virtual ~Observer() = default;
};

// 具體觀察者
class MyClass : public Observer {
public:
    void update(int value) override { 
        std::cout << "Config changed to " << value << std::endl; 
    }
};

方案三:C++20 std::atomic + 條件變量(無鎖輪詢替代)


std::atomic g_value{0};
std::condition_variable g_cv;
std::mutex g_cv_mtx;

void watcherThread() {
    int last = g_value.load();
    while (running) {
        std::unique_lock lock(g_cv_mtx);
        // 等待變化或超時
        g_cv.wait_for(lock, 100ms, [&]{ return g_value.load() != last; });
        int current = g_value.load();
        if (current != last) {
            last = current;
            onValueChanged(current); // 在鎖外調用
        }
    }
}

void setter(int newVal) {
    g_value.store(newVal);
    g_cv.notify_one(); // 喚醒等待線程
}

避坑指南

  1. 全局變量本身不安全:必須用 std::atomic 或 mutex 保護
  2. 回調執行上下文:Setter 線程直接調用回調,若耗時操作會阻塞設值,建議異步分發
  3. 生命週期管理:觀察者銷毀時必須 detach,否則野指針崩潰
  4. 遞歸觸發:回調中修改同一變量會導致無限循環,需變化檢查(if (old != new))
  5. 複製回調列表:遍歷前複製,防止回調中 attach/detach 導致迭代器失效

總結

全局變量監控不推薦多線程輪詢(資源浪費、延遲不可控)。首選封裝 Setter + 回調,簡單高效;複雜場景用觀察者模式,解耦合擴展性強;高性能無鎖用 atomic + condition_variable。核心原則:封裝變量、顯式變更通知、線程安全、生命週期管理。將全局變量升級為「可觀察對象」,是從 C 風格邁向 C++ 現代設計的關鍵一步。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved