2016-05-20 3 views
-1
class log_String { 
    //These are private! 
    std::vector<std::string> list; 
    std::mutex m; 
    log_String& operator=(const log_String &source); //Operatore assegnazione 
    log_String(const log_String &source); 

public: 
    log_String() {}; // <---- is this thread_safe? 

    void add(std::string string) { 
    std::lock_guard<std::mutex> l(m); 
    list.push_back(string); 
    } 

    void printFile(std::string file) { 
    std::lock_guard<std::mutex> l(m); 
    std::ofstream myfile; 

    myfile.open(file); 
    for (auto iterator = list.begin(); iterator != list.end(); ++iterator) { 
     myfile << *iterator << "\n"; 
    } 
    } 
}; 

log_String() {} нить-сейф? Я думаю, что даже если многие потоки звонят одновременно log_String() {}, это не должно быть проблемой? Неужели я ошибаюсь? Если я ошибаюсь, возможно, это решение может определить его private и защитить экземпляр нового объекта, приобретающего новый замок?Является ли по умолчанию конструктором потокобезопасным в C++?

+4

Этот вопрос не имеет смысла. Конструктор запускает * до *, время жизни объекта начинается. Как можно получить доступ к объекту *, который не существует, несколькими потоками одновременно? –

+0

@KerrekSB Ваш комментарий должен был быть ответом! В качестве примечания: я задал вопрос о том, как начинается срок жизни объекта (http://stackoverflow.com/questions/20409500/what-does-the-c-standard-mean-regarding-object-lifetime-begins) и получили интересные ответы. Что означает «инициализация завершена» в стандартном значении? :) – mantler

+1

@GeorgeAl: Что? Как? Когда? –

ответ

2

log_String() в основном функция, но она также является конструктором. Таким образом, его вызов при создании объекта означает также рекурсивно вызывать конструкторы всех переменных-членов (которые имеют конструкторы), а также конструкторы всех базовых классов и конструкторы их переменных-членов.

Итак, вам нужно рассмотреть все функции, которые вызывают. Две переменные-члены, list и m, должны иметь поточно-безопасные конструкторы, так как они из стандартной библиотеки, и пока я не проверял со стандарта (черновик должен быть свободно загружаемым, если вы хотите проверить себя), все будет быть просто сумасшедшим, если у них нет потокобезопасных конструкторов. Тогда нет базового класса и никакого кода в вашем конструкторе.

Заключение, это поточно-, потому что нет ничего в там, что может вызвать проблемы «даже если много потоков вызова одновременно log_String()». Не отображаются общие данные или другие общие ресурсы, и если в переменных-членах есть какие-либо общие данные, им можно доверять, чтобы их можно было безопасно выполнять.

Написание небезопасных общественных конструкторов можно считать глупыми, даже злыми. Тем не менее, если у вас есть переменные-члены или базовый класс из сторонних библиотек или только ваши собственные типы, и вы не на 100% уверены в их качестве, то стоит остановиться и подумать, была ли эта глупость ,


Пример код, который можно было бы правдоподобно писать, особенно для целей отладки, и которые бы сделать вещи поточно-небезопасный:

private: 
    static unsigned static_counter; 

public: 
    log_String() { 
     ++static_counter; // not atomic operation! potential data race! 
    }; 

Для полноты: Фикс для приведенной выше коды будут просто используйте std::atomic<unsigned> для счетчика. Для более сложных случаев могут потребоваться статические мьютексы (будьте осторожны, если вы используете старые компиляторы crappy (по крайней мере, MSVC2010), которые могут иметь неизбежные условия гонки со статическими данными).

Смежные вопросы