【问题标题】:Is reading and writing to the same file thread-safe?读写同一个文件是线程安全的吗?
【发布时间】:2014-03-13 00:31:07
【问题描述】:

我有一个名为“data.txt”的文件。

我有两个线程。

第一个线程,读取文件的全部内容:

while(1){
    char buf[1000];
    FILE* fp = fopen("data.txt","r");
    while(fread(buf,1,1000,fp)>0){
        /* process data */
    }
    fclose(fp);
}

第二个线程将数据追加到文件中:

while(1){
    FILE* fp = fopen("data.txt","a");
    fwrite("hello\n",1,6,fp);
    fclose(fp);
}

在这种情况下读写(WHITOUT any MUTEX or FILELOCKING)是线程安全的吗? (没有分段错误等...)

【问题讨论】:

  • 我可能错了,但我相信 POSIX 只指定操作系统接口,而不是 C 库。因此,如果 fwrite 和 fread 是线程安全的,POSIX 不知道。它确实指定 read() 和 write() 是线程安全的。
  • 我怀疑你会崩溃,但我也怀疑你的阅读线程从文件中读取的数据会特别明确。特别是,如果您希望文件表现得像 FIFO 管道(线程 2 写入的每个字节稍后都会按顺序由线程 1 读取),您可能会感到失望。
  • 你试过了吗?它应该很容易证明它不安全。
  • 感谢您的回复。在 windows 和 Fedora 上,根本没有分段错误。所以我认为它是线程安全的......
  • 没有分段错误并不意味着线程安全。

标签: c multithreading posix


【解决方案1】:

首先,大多数标准库函数,除了显式解锁的 I/O 函数之外,都是官方线程安全的。见http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.htmlhttp://pubs.opengroup.org/onlinepubs/009695299/functions/flockfile.html 明确指出,flockfile() 不需要,除非有特殊要求。

关于非线程安全的 unlocked 函数的评论很有趣:

当且仅当在调用线程拥有 (FILE *) 对象时调用这些函数时,这些函数可以安全地在多线程程序中使用,就像在成功调用 flockfile() 或 ftrylockfile( ) 函数。

这意味着正常的线程安全保证,锁定函数比你正在做的要强:即使使用相同的FILE指针,它们也是安全的(one fopen() 的结果)。很容易看出同时更新 FILE 结构中的簿记信息会如何破坏它;正常的标准库函数保证不会。

另一方面,C 标准说:“同一个文件是否可以同时打开多次也是实现定义的。”有CERT advisory 可以避免这种情况。这是多个FILE 结构的用例,通过两个fopen() 调用获得,可能没有干预fclose(),对同一个底层物理文件。

该标准定义此实现可能反映某些操作系统的(潜在)限制。

附注:多次成功尝试并发算法并不能保证它是正确的。并发问题是可怕的野兽,以不可预测的方式抬起头。

【讨论】:

    【解决方案2】:

    fread()fwrite() 本质上是线程安全的。它们不太可能导致你的程序崩溃,但不能保证读写的顺序。

    如果您打算同时使用flockfile()funlockfile(),则必须使用它们。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-03
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 2010-09-13
    相关资源
    最近更新 更多