为什么我实现单例实例化两次? (一个过程,几个线程)

时间:2014-02-12 07:33:43

标签: c++ singleton

我有静态库,其中包含这样的单例定义:

    class InstrumentsStorage
    {
    public:
        static InstrumentsStorage& getInstance() {
            static InstrumentsStorage instance;
            return instance;
        }
        // methods
    private:
        InstrumentsStorage();
        InstrumentsStorage(InstrumentsStorage const&);
        void operator=(InstrumentsStorage const&);

        // fields
    };

我添加了这样的跟踪:

InstrumentsStorage::InstrumentsStorage() {
    std::cout << "InstrumentsStorage constructor called!" << std::endl;
            ...

在我的日志中,我发现这个字符串两次。为什么?如何修复我的单例,因此只创建了一个实例。我可以使用C ++ 11。

我正在使用来自不同线程的不同项目的单例,但我只有一个进程。

更新添加完整列表:

#pragma once

#include <string>
#include <iostream>
#include <boost/unordered_map.hpp>
#include "CommonsNative.h"

class InstrumentsStorage
{
public:
    static InstrumentsStorage& getInstance() {
        static InstrumentsStorage instance;
        return instance;
    }
    int GetInstrumentId(std::string& instrument);
    std::string& GetClassCode(int instrumentId) {
        return classcodes[instrumentId];
    }
    std::string& GetTicker(int instrumentId) {
        return tickers[instrumentId];
    }
private:
    InstrumentsStorage();
    InstrumentsStorage(InstrumentsStorage const&);
    void operator=(InstrumentsStorage const&);

    boost::unordered_map<std::string, int> instrument2id;
    std::string classcodes[MAX_INSTRUMENTS_NUMBER_IN_SYSTEM];
    std::string tickers[MAX_INSTRUMENTS_NUMBER_IN_SYSTEM];
};

cpp:

#include "InstrumentsStorage.h"
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <iostream>

InstrumentsStorage::InstrumentsStorage() {
    std::cout << "InstrumentsStorage constructor called!" << std::endl;
    boost::property_tree::ptree pt;
    boost::property_tree::ini_parser::read_ini("config_generated/instruments_gate_0.txt", pt);

    for (auto& section : pt)
    {
        std::string instrument = section.first;
        int id =  section.second.get_value<int>();
        instrument2id[instrument] = id;
        std::cout << "InstrumentsStorage Assigned instrument = " << instrument << " id = " << id << std::endl;
        classcodes[id] = instrument.substr(0, 4);
        tickers[id] = instrument.substr(4, std::string::npos);
        std::cout << "InstrumentsStorage id " << id << " classcode = " << classcodes[id]
                << " ticker = " << tickers[id] << std::endl;
    }
}

int InstrumentsStorage::GetInstrumentId(std::string& instrument)
{
    // std::cout << "InstrumentsStorage GetInstrumentId called, instrument = " << instrument << std::endl;
    boost::unordered_map<std::string, int>::iterator i = instrument2id.find(instrument);
    if (i == instrument2id.end())
    {
        // std::cout << "InstrumentsStorage GetInstrumentId not found, result == -1 " << std::endl;
        return -1;
    } else
    {
        // std::cout << "InstrumentsStorage GetInstrumentId found, result = " << i->second << std::endl;
        return i->second;
    }
}

2 个答案:

答案 0 :(得分:0)

如果您需要线程安全的单例,则必须实现自己的锁定机制。在C ++ 11中这样做的最简单方法是:

#include <mutex>

class Singleton 
{
    static Singleton *singletonInstance;
    Singleton() {}
    static std::mutex m_;

  public:

    static Singleton* getSingletonInstance()
    {
        std::lock_guard<std::mutex> lock(m_);
        if(singletonInstance == nullptr)
        {
            singletonInstance = new Singleton();
        }
        return singletonInstance;
    }
}

实现它的另一种方法,或许更简单,就是使用一次性函数:

#include <mutex>

static void init_singleton() {
    singletonInstance = new Singleton;
}

static std::once_flag singleton_flag;

Singleton* getSingletonInstance() {
    std::call_once(singleton_flag, init_singleton);
    return singletonInstance;
}

即使您的编译器可能无法完全实现C ++ 11并发模型尚未,上述两种方法都可以工作:

static Foo& getSingleton() { 
    static Foo foo;
    return foo;
}

正常工作

答案 1 :(得分:0)

我不确定您的问题是否已解决。看代码,似乎静态变量只应实例化一次,因此它的构造函数应该只被调用一次。可能是其他时间在您的代码中调用的构造函数。 你能在构造函数中设置断点并调试它来检查。它可以帮助您更快地找到问题。