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

C fopen()在Linux中是线程安全的函数吗?,c,linux,multithreading,mutex,C,Linux,Multithreading,Mutex,如果我使用fopen()调用在多线程中打开同一个文件,并将数据写入该文件。我应该使用互斥锁来确保数据不会混乱吗?据我所知,您应该使用互斥锁 我没有尝试过这是C,但是在Java中,如果在多个线程中打开文件,两个线程都可以写入,而且文件确实是一团糟 因此,我认为C中的情况相当于Javafopen()是可重传的,您可以有任意多个描述符指向同一个文件 使用多个描述符对文件进行读写的结果不是线程安全问题,而是并发文件访问,这在大多数情况下(除了文件为只读时)都无法正常工作。如果两个线程都使用fopen()

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

据我所知,您应该使用
互斥锁

我没有尝试过这是
C
,但是在
Java
中,如果在多个
线程中打开
文件
,两个
线程都可以写入,而且
文件
确实是一团糟

因此,我认为
C
中的情况相当于
Java

fopen()
是可重传的,您可以有任意多个描述符指向同一个文件


使用多个描述符对文件进行读写的结果不是线程安全问题,而是并发文件访问,这在大多数情况下(除了文件为只读时)都无法正常工作。

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

引用
(文件*)
对象的所有函数(名称以
\u unlocked
结尾的函数除外)的行为应如同它们在内部使用
flockfile()
funlockfile()
来获得这些(文件*)对象的所有权一样

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


顺便说一句,如果您以追加模式打开文件(
O_append
with
open()
,使用
“a”
with
fopen()
),那么所有写入都应该在文件的末尾,并且您不应该因为交叉写入而遇到麻烦-除非,您的独立线程正在使用文件流并一次写入超过一个缓冲区的内容,或者在写入每行输出的一部分后使用
fflush()
,或者每次使用
write()
或其众多亲戚之一写入一行的一部分。即使使用附加模式,也有可能遇到问题,但您通常必须尝试遇到这些问题。

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

欢迎提出任何建议

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;
}
类OpenFile
{
字符串文件名;
静态地图fmap;
布尔旗;
公众:
OpenFile(字符串文件):文件名(文件){
试一试{
如果(检查文件(文件))
{
flag=false;
emplace(文件,make_unique());
}
其他的
{
flag=true;
}
}
捕获(字符串str)
{

cout问题不在于fopen(),而在于如何写入文件。您需要做一些事情(例如互斥)来控制写入。“记录锁定”也是一个选项。它使您能够锁定文件的不同范围。不同的线程可以同时写入文件的不同部分。实际上,我是说您应该尝试一下。运行两个线程,您将看到文件将多么混乱。我在猜测什么?“所以我认为C中的情况将等同于Java。”-这可以很容易地写成评论,而不是答案。我不确定我是否理解,如果我同时访问(读/写)不同的文件,我是否会认为会有问题?@ransh:如果在不同的文件上打开两个文件流,就不会有问题。如果在同一个文件上打开,就会有问题。