簡體   English   中英

C ++中的單例多線程代碼

[英]Singleton multithread code in C++

我懷疑與C ++中的Singleton和多線程編程有關。接下來,您將看到一個Singleton類的示例代碼,其中包含一個名為shared的變量。

我創建1000個線程來修改(+1)我的Singleton全局實例的變量。 shared的最終值為1000,但是我希望該值小於1000,因為我沒有為並發保護此變量。

代碼是真正的線程安全的,是因為類是Singleton,還是碰巧很幸運,值是1000,但可以完美地小於1000?

#include <iostream>
using namespace std;

class Singleton {
private:
    Singleton() {shared = 0;};
    static Singleton * _instance;
    int shared;

public:
    static Singleton* Instance();
    void increaseShared () { shared++; };
    int getSharedValue () { return shared; };
};

// Global static pointer used to ensure a single instance of the class.
Singleton* Singleton::_instance = NULL;

Singleton * Singleton::Instance() {
    if (!_instance) { 
        _instance = new Singleton;
    }

    return _instance;
}

void * myThreadCode (void * param) {
    Singleton * theInstance;
    theInstance = Singleton::Instance();
    theInstance->increaseShared();

    return NULL;
}

int main(int argc, const char * argv[]) {
    pthread_t threads[1000];
    Singleton * theInstance = Singleton::Instance();

    for (int i=0; i<1000; i++) {
        pthread_create(&threads[i], NULL, &myThreadCode, NULL);
    }

    cout << "The shared value is: " << theInstance->getSharedValue() << endl;

    return 0;
}

代碼是真正的線程安全的,是因為類是Singleton,還是碰巧很幸運,值是1000,但可以完美地小於1000?

你真是幸運...

實際上,觀察到的最可能問題與事實有關,即在特定計算機上增加單例的值所花費的時間少於操作系統分配資源所花費的時間。啟動一個單獨的pthread。 因此,您永遠不會遇到兩個線程爭奪單例未受保護資源的情況。

更好的測試方法是先啟動所有 pthread,讓它們在屏障或條件變量上阻塞,然后在滿足所有線程“活動”的屏障條件后,對單例執行遞增操作。到那時,您將更有可能看到非原子操作(例如增量操作)發生的各種數據爭用。

如果您這樣實現Singleton ,則Singleton創建將是線程安全的:

Singleton & Singleton::Instance() {
    static Singleton instance;
    return instance;
}

由於實例永遠不能為null,也沒有管理者的內存,因此將返回引用而不是指針。

可以通過使用特定於平台的操作(g ++提供內置功能,例如__sync_fetch_and_add ),STL中的C ++ 11原子或Boost.Atomic或互斥保護來使增量操作成為原子操作。

std::atomic<int> shared;

void increaseShared () { ++shared; };

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM