If I use fopen() call to open a same file in multi-thread, and write data to the file. Should I use a mutex to ensure the data won't be disordered?
问题:
回答1:
If two threads both open the same file with fopen()
, they will each have independent file streams (FILE *
) backed by independent file descriptors referring to the same file. You can write independently to the two file streams, but the net result on the file will depend on where the threads write and when they flush the file stream. The results are unpredictable unless you control where each thread is writing. The simplest thing is to make sure both threads use the same file stream, but you probably still need to coordinate between the threads. Note that POSIX requires the C functions to give coordinated access to the file stream — see flockfile()
which imposes the requirement that
All functions that reference
(FILE *)
objects, except those with names ending in_unlocked
, shall behave as if they useflockfile()
andfunlockfile()
internally to obtain ownership of these (FILE *) objects.
If you open the file in append mode in both threads, then the writes would be safely at the end of the file each time, but you still have to worry about flushing the data before the buffer fills.
回答2:
As far as I know you should use mutexes
.
I hadn't try this is C
, but in Java
if you open a file
in more than one thread
, both threads
can write in it and file
is really messed up.
So I think the situation in C
will be equivalent to Java
.
回答3:
fopen()
is reenterable, and you can have as many descriptors pointing to the same file as you like.
What you get as a result of reading/writing from/to the file using multiple descriptors is not a thread safety question, but rather concurrent file access, which in most cases (apart from when the file is read-only) won't work well.
回答4:
Below is a thread safe open file write you can open multiple files and it just write to the file sequentially. I think the below code can be still optimized with time sync and popping out unused files to maintain cache
Any suggestion is welcome
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;
}