2017-10-07 7 views
0

私はC++ 11の処理を他のサービスから遅れて処理することをシミュレートしようとしましたsleep_forランダムな時間。C++ 11 async&future output orderless

// g++ f1.cpp -o f1 -std=c++11 -lpthread 
#include <future> 
#include <iostream> 
#include <vector> 
#include <chrono> 
#include <thread> 
#include <random> 
#include <fstream> 

using namespace std; 

ofstream fout("log.txt"); 

int twice(int m) { 
    random_device rd; 
    int isleept = rd() % 100 + 1; 
    this_thread::sleep_for(chrono::milliseconds(isleept)); 
    fout << m << " done with " << isleept << " milliseconds" << endl; 
    return 2 * m; 
} 

int main() { 
    vector<future<int> > futs; 

    for (int i=0; i<10; i++) { 
     futs.push_back(async(twice, i)); 
    } 

    for (auto &e : futs) { 
     e.get(); 
    } 

    return 0; 
} 

私はコンパイル済みのファイルを実行したときに、出力ファイルはORDERLESSを思わ:

9 done with 3 milliseconds 
8 done with 8 milliseconds 
3 done with 32 milliseconds33 milliseconds 

3 done with 32 milliseconds33 milliseconds 

6 done with 35 milliseconds 
7 done with 38 milliseconds 
540 milliseconds 
2 done with 54 milliseconds 
1 done with 65 milliseconds 
4 done with 83 milliseconds 

私はどのように私は私のプログラムを改善することが不思議でしたか?

+3

これは、ここでの主な問題ではないですが、あなたはランダムエンジン(例えばmt1997)を使用する必要がありますと ' std :: uniform_int_distribution'は、ランダムなデバイスの出力にモジュロを適用しません。 – einpoklum

答えて

3

このプログラムはデータ競合を引き起こします。すなわち、foutは、適切なロックなしに複数のスレッドから同時に呼び出されます。

ロック機構を追加することをおすすめします。たとえば、あなたがstd::mutexを追加し、そのstd::mutexの上にstd::lock_guardを使用してログファイルに出力をロックすることがあります

std::mutex io_mutex; 

int twice(int m) { 
    random_device rd; 
    int isleept = rd() % 100 + 1; 
    this_thread::sleep_for(chrono::milliseconds(isleept)); 

    std::lock_guard<std::mutex> lock(io_mutex); 
    fout << m << " done with " << isleept << " milliseconds" << endl; 

    return 2 * m; 
}