2016-05-20 6 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()は基本的には機能ですが、コンストラクタでもあります。つまり、オブジェクト作成時の呼び出しは、コンストラクタを持つすべてのメンバ変数のコンストラクタ、すべての基本クラスのコンストラクタ、およびメンバ変数のコンストラクタを再帰的に呼び出すことを意味します。

したがって、呼び出されるすべての関数を考慮する必要があります。 listmの2つのメンバ変数は、標準ライブラリのものであり、標準からチェックしていないので(スレッドを自由にダウンロードできるようにする必要があります)、スレッドセーフなコンストラクタが必要です。スレッドセーフなコンストラクタを持っていなければちょうど狂っているでしょう。次に、基本クラスはなく、コンストラクタにはコードはありません。問題を引き起こすそこでは何も、ありませんので

結論、それは、スレッドセーフである「多くのスレッドが同時にlog_String呼び出しても()」。共有データやその他の共有リソースは表示されません。また、メンバー変数に隠された共有データがある場合は、それらを安全に行うことができます。

スレッドで安全でないパブリックコンストラクタを書くことは、愚かでも悪であるとみなすことができます。それでも、サードパーティのライブラリや、自分のタイプのメンバー変数や基底クラスがあって、その品質が100%保証されていない場合は、この種の愚かさが止まったら。

private: 
    static unsigned static_counter; 

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

完全性について:上記のコードを修正するだろうスレッドセーフでないが、物事はなるだろう


例1は、もっともらしく、特にデバッグ目的のために、書き込み可能性のあるコード、およびカウンターには単にstd::atomic<unsigned>を使用してください。より複雑なケースでは、静的なミューテックスが必要になる場合があります(静的なデータとの競合が避けられない古いクラッピーコンパイラ(MSVC2010以上)を使用している場合は注意してください)。

関連する問題