2

この関数は、ofstream を参照として受け取り、構造体パケットを構築し、ofstream を使用して構造体からトライ一致クラスへのスレッドを作成します。スタックは、マッチ距離の順に n 個のマッチで返されます。次に、ofstream、パケット、およびスタックは、一致を同じ出力ファイルに書き込む print 関数への参照によって渡されます - ofstream が使用されていないときを待ちます。問題は、マッチの半分が書き込まれた後に ofstream がクラッシュすることです。

ofstream、パケット、および outfile ヘッダー

void Match_Import_Start(Trie & tri)
{
    stack<Trie::MatchesT> out;
    ofstream myfile;
    Trie::MatchesT matchSet;

    myfile.open(outFile.c_str() );
    myfile << "DESCRIPTION,SUGGESTED.DESCRIPTION,EDIT" << "\n"; //write header
    myfile.close();

    Match_Import (tri, myfile, out, matchSet);

    return;
}

レコード リストからスレッドを生成する

void Match_Import(Trie &tri, ofstream &myfile, stack<Trie::MatchesT> out, Trie::MatchesT matchSet)
{   
    out=parse_CSV_file(timeFile); //read in records

    settingT x;

    x.score=0;

    boost::thread_group tgroup; //http://stackoverflow.com/questions/8744279/create-threads-in-a-loop
    while (!out.empty() ) {
        matchSet=out.top();
        out.pop();

        tgroup.create_thread(boost::bind( MaxDistanceCorrections, boost::ref(tri), matchSet, boost::ref(myfile), boost::ref(x) ) );
    }
    tgroup.join_all();

    return;
}

マッチからの有効な復帰を確認する

void MaxDistanceCorrections(Trie & tri, Trie::MatchesT matchSet, ofstream &myfile, settingT &x)
{
    if (!matchSet.candidateStack.empty() ) ) {
        matchSet.candidateStack.sort(compareCorrMain);
        PrintCorrections(tri, matchSet, myfile, x);
        return;

    } else {        
        tri.suggest(matchSet); //send out to trie match

         if (matchSet.candidateStack.empty() ) { }// modify match parameters

        MaxDistanceCorrections(tri, matchSet, myfile, x);
    }
}

ofstream が利用可能になったときに出力します

void PrintCorrections(Trie &tri, Trie::MatchesT &matchSet, ofstream &myfile, settingT &x)
{   
    while (true) {
        if (!myfile.is_open() ) { 
          myfile.open(outFile.c_str(), ios::out | ios::app);
          break;
        }  
     }

    while (!matchSet.candidateStack.empty() ) {
        Trie::CorrectionT corr=matchSet.candidateStack.back();
        matchSet.candidateStack.pop_back();

        const bool flagGood=scoreSuggest (corr); //score
        if (flagGood ) x.score++;

        myfile << matchSet.testCase << "," << corr.match << "," << corr.editDistance << "\n";

    }
    myfile.close();

    return;
}

マルチスレッドではかなり新しい機能ですが、これらの関数はシングル スレッドとして問題なく動作しました。

ofstream available のチェックは、候補の一致をスピンオフする while ループ内に配置する必要がありますか? ofstream が利用可能になると、印刷シーケンスを開始すると、他のスレッドから ofstream を結び付ける必要があります。

複数のスレッドで共有される ofstream の使用を予約するより良い方法はありますか?

4

2 に答える 2

3

マルチスレッドを初めて使用する場合は、これをミューテックスロックを使用する理由のレッスンにしましょう。

オブジェクトはまさにそれfstreamです-オブジェクト。ミューテックスを使用して、同時アクセスから保護する必要があります。

スレッドがファイルに情報を書き込めるようにするだけの場合は、代わりに。stringの代わりにファイル名を(として)渡すことができますfstream。その後、スレッドは排他的な読み取り/書き込みアクセスでファイルを開くことができます。これはローカルfstreamオブジェクトを使用し、ロックはオペレーティングシステムによって処理されます。

于 2013-03-20T01:23:58.857 に答える
2

このコードは、複数のスレッドからの未定義の動作を示します。N3485 27.2.3 [iostreams.threadsafety]/1を参照してください。

複数のスレッドによるストリームオブジェクト(27.8、27.9)、ストリームバッファオブジェクト(27.6)、またはCライブラリストリーム(27.9.2)への同時アクセスは、特に指定されていない限り(27.4)、データ競合(1.10)を引き起こす可能性があります。[注:データの競合により、未定義の動作が発生します(1.10)。—エンドノート]

一般的なケースでは、ストリームをスレッド間で安全に使用することはできません。などのロックを使用してストリームを保護する必要がありますstd::mutex

ストリームがスレッド間で安全にアクセスできる場合でも、このコードはおそらくあなたが望むことをしないことに注意してください。次の行を検討してください。

myfile << matchSet.testCase << "," << corr.match << corr.editDistance << "\n";

これはと同じです

myfile << matchSet.testCase;
myfile << ",";
myfile << corr.match;
myfile << corr.editDistance;
myfile << "\n";

競合状態に注意してください。operator<<ストリームの実装が実装によって同期されているとしましょう。この外部コードにはまだ潜在的な競争があります。たとえば、2つのスレッドでこれを実行できる可能性があるのは次のとおりです。

   Thread 1                              Thread 2
======================================================================
myfile << matchSet.testCase;
                                         myfile << matchSet.testCase;
myfile << ",";
                                         myfile << ",";
myfile << corr.match;
myfile << corr.editDistance;
myfile << "\n";
                                         myfile << corr.match;
                                         myfile << corr.editDistance;
                                         myfile << "\n";

それを1行で書く代わりに、各スレッドからの出力が混同されて、ぎこちない結果になります。

于 2013-03-20T01:23:02.623 に答える