繁体   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