fopen()是Linux中的线程安全函数吗?

时间:2013-05-29 06:32:59

标签: c linux multithreading mutex

如果我使用fopen()调用在多线程中打开一个相同的文件,并将数据写入该文件。我应该使用互斥锁来确保数据不会混乱吗?

4 个答案:

答案 0 :(得分:14)

如果两个线程都使用fopen()打开同一个文件,则它们每个都有独立的文件流(FILE *),由引用同一文件的独立文件描述符支持。您可以独立写入两个文件流,但文件的最终结果将取决于线程写入的位置以及它们刷新文件流的时间。除非您控制每个线程的写入位置,否则结果是不可预测的。最简单的方法是确保两个线程使用相同的文件流,但您可能仍需要在线程之间进行协调。请注意,POSIX要求C函数提供对文件流的协调访问 - 请参阅flockfile(),其中强制要求

  

引用(FILE *)个对象的所有函数,除了名称以_unlocked结尾的对象外,其行为应该像在内部使用flockfile()funlockfile()一样获得这些对象的所有权( FILE *)对象。

如果在两个线程中以附加模式打开文件,那么每次写入都会安全地写在文件的末尾,但是你仍然需要担心在缓冲区填满之前刷新数据。

顺便提一下,如果您以追加模式(O_APPENDopen()打开文件,使用"a"fopen()),那么所有写入都应该在文件,你应该不会遇到交错写入的问题 - 除非你的独立线程可能使用文件流并且一次写入多个缓冲区,或者在写入每个部分后使用fflush()输出行,或者他们每次使用write()或其无数亲戚之一来编写行的部分。即使使用追加模式,也有办法遇到问题,但您通常必须尝试遇到它们。

答案 1 :(得分:1)

fopen() reenterable ,您可以拥有指向同一个文件的任意数量的描述符。

使用多个描述符从/向文件读取/写入的结果不是线程安全问题,而是并发文件访问,在大多数情况下(除了文件是只读的)工作得很好。

答案 2 :(得分:1)

下面是一个线程安全的打开文件写入,你可以打开多个文件,它只是顺序写入文件。 我认为下面的代码仍然可以通过时间同步进行优化,并弹出未使用的文件来维护缓存

欢迎任何建议

class OpenFile
{
    string fileName;
    static map<string, unique_ptr<mutex>> fmap;
    bool flag;
public :
    OpenFile(string file) : fileName(file) {
        try {
            if(checkFile(file))
            {
                flag = false;
                fmap.emplace(file, make_unique<mutex>());
            }
            else
            {
                flag = true;
            }
        }
        catch(string str)
        {
            cout << str << endl;
        }
    }
    void writeToFile(const string& str) const
    {
        if (flag)
        {
            lock_guard<mutex> lck(*fmap.find(fileName)->second);
            ofstream ofile(fileName, ios::app);
            ofile << "Writing to the file " << str << endl;
            ofile.close();
        }
        else
        {
            ofstream ofile(fileName, ios::app);
            ofile << "Writing to the file " << str << endl;
            ofile.close();
        }
    }
    string ReadFile() const
    {
        string line;
        if (flag)
        {
            lock_guard<mutex> lck(*fmap.find(fileName)->second);
            ifstream ifile(fileName, ios::in);
            getline(ifile, line);
            ifile.close();
        }
        else
        {
            ifstream ifile(fileName, ios::in);
            getline(ifile, line);
            ifile.close();
        }
        return line;
    }
    OpenFile() = delete;
    OpenFile& operator=(const OpenFile& o) = delete;
    static bool checkFile(string& fname);
};


bool OpenFile::checkFile(string& fname)
{
    if (fmap.find(fname)==fmap.end())
    {
        return true;
    }
    else
        return false;
}

答案 3 :(得分:0)

据我所知,你应该使用mutexes

我没有尝试这是C,但在Java中,如果您在多个file中打开thread,则threads都可以写在其中file真的搞砸了。

所以我认为C中的情况将等同于Java