多线程共享的ofstream-一段时间后崩溃 [英] ofstream shared by mutiple threads - crashes after awhile

查看:418
本文介绍了多线程共享的ofstream-一段时间后崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此函数以ofstream作为参考,然后构建结构数据包,并使用ofstream将结构从线程中分离到Trie匹配类.根据匹配距离的顺序返回具有n个匹配项的堆栈.然后,通过引用将ofstream,数据包和堆栈传递给打印函数,该函数将匹配项写入相同的输出文件-等待不使用ofstream时.问题是写了一半的比赛后,ofstream崩溃了.

this function takes a ofstream as a reference, then builds struct packets and threads off the structs with the ofstream to a trie matching class. A stack is returned with n matches in order of match distance. The ofstream, packet, and stack are then passed by reference to a print function that writes the matches to the same output file - waiting for when the ofstream is not in use. The problem is the ofstream crashes after half the matches are written.

ofstream,数据包和外文件头

The ofstream, packet, and outfile header

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可用时打印

and print when ofstream is available

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;
}

这是mutithreading的新功能,这些功能可以作为单线程很好地工作.

Fairly new at mutithreading, these functions worked fine as a single thread.

是否应该对ofstream进行检查,将其放入分离候选匹配项的while循环中?一旦ofstream可用,则开始打印序列应将ofstream与其他线程捆绑在一起.

Should the check for ofstream available be placed within the while loop that spins off the candidate matches? Once the ofstream is available then starting the print sequence should tie-up the ofstream form other threads.

是否有更好的方法来保留对多个线程共享的ofstream的使用?

Is there a better way to reserve use of an ofstream shared by multiple threads?

推荐答案

此代码显示了来自多个线程的未定义行为.参见N3485 27.2.3 [iostreams.threadsafety]/1:

This code exhibits undefined behavior from multiple threads. See N3485 27.2.3 [iostreams.threadsafety]/1:

除非另有指定(27.4),否则多个线程同时访问流对象(27.8、27.9),流缓冲区对象(27.6)或C库流(27.9.2)可能会导致数据争用(1.10). [注意:数据争用导致未定义的行为(1.10). —尾注]

Concurrent access to a stream object (27.8, 27.9), stream buffer object (27.6), or C Library stream (27.9.2) by multiple threads may result in a data race (1.10) unless otherwise specified (27.4). [ Note: Data races result in undefined behavior (1.10). —end note ]

在一般情况下,跨线程使用流是不安全的.您必须使用锁来保护流,例如std::mutex.

In the general case, streams are not safe to use across threads. You must protect the stream using a lock, such as std::mutex.

请注意,即使可以安全地跨线程访问流,此代码也可能不会执行您想要的操作.考虑这一行:

Note that even if streams were safe to access across threads this code would probably not do what you want. Consider this line:

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

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

注意比赛条件.假设您的实现的operator<<流是由实现为您同步的.在此外部代码中,您仍然有潜在的竞争.例如,这是在2个线程中执行此操作的一种可能的方法:

Note the race condition. Let's say that your implementation's operator<< for streams is synchronized for you by the implementation. You still have a potential race in this outer code. For instance, here is one possible execution of this across 2 threads:

   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";

您将获得的每个线程的输出混合在一起,而不是单行地写,从而导致乱码.

Instead of getting that to write as a single line, you'll get output from each thread mixed up together, resulting in gibberish.

这篇关于多线程共享的ofstream-一段时间后崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆