c - 以下使用 FILE*、ftell、fwrite 和 fflush 的代码线程安全吗?

标签 c multithreading thread-safety

在下面的代码中,我的函数将数据条目写入磁盘,并且应该将偏移量返回到记录该条目的文件中。但是,当在多个线程中运行代码时,我发现有时该值不准确。这段代码有线程安全问题吗?

// global file descriptor to current data file, shared amongst many threads
FILE* current_fp;
pthread_mutex_t my_mutex;
...

int main()
{
    ...
    pthread_mutex_lock(&my_mutex);

    current_fp = fopen(data_file, "ab");
    if (current_fp == NULL)
    {
       fprintf(stderr, "%s: Unable to open file %s: %s\n", __func__, data_file, strerror_r(errno, ebuf, sizeof(ebuf)));
       pthread_mutex_unlock(&ldb_mutex);
       return -1;
    }

    pthread_mutex_unlock(&my_mutex);  

    return 0;
}

// write a data entry, and return the offset at which it will be stored
// I'm having an issue where it seems like *occasionally* the offset returned is not
// really the offset at which the entry was stored, with multiple threads
long write_log_entry(data_entry_t* entry)
{
   int num_written; 
   long offset; // offset at which entry will be written

   pthread_mutex_lock(&my_mutex);

   // get the next offset in the file, which is where I expect
   // the entry to be stored
   offset = ftell(current_fp);
   if (offset == -1)
   {
      error();
   }

   // an example -- the real code writes a bunch of data members of entry
   int num_written = fwrite(entry, sizeof(data_entry_t), 1, current_fp);
   if (num_written != 1) 
   {
       error();
   }

   fflush(current_fp);

   pthread_mutex_unlock(&my_mutex);

   return offset; 
}

最佳答案

也许问题与 fopen 手册中描述的行为有关:

'请注意,ANSI C 要求在输出之间插入文件定位函数 和输入,除非输入操作遇到文件结尾。 (如果不满足此条件,则允许读取返回其他写入的结果 比最近的。)因此这是一个很好的做法(实际上有时 在 Linux 下是必需的),在两者之间放置 fseek(3) 或 fgetpos(3) 操作 对此类流进行写入和读取操作。这个操作可能是一个明显的 无操作(如 fseek(..., 0L, SEEK_CUR) 调用其同步端 效果。'

ftell 可能被视为读取操作。尝试在 ftell 之前插入 fseek(..., 0L, SEEK_CUR) 看看是否有帮助。

关于c - 以下使用 FILE*、ftell、fwrite 和 fflush 的代码线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11298889/

相关文章:

java - 在多线程环境中初始化EntityManagerFactory

c# - TryGetValue 线程本身是否安全

c - 变量或字段声明为空”和其他错误

c - 如何通过 C 库获取 Linux 硬件和系统信息?

c - `off_t` 之前的预期表达式

c++ - 多个线程竞相将相同的数据设置为相同的值

Java Swing 马模拟

c# - 线程间基于回合的同步

php - PHP 中什么是线程安全或非线程安全?

c - Atmel Studio 6.1 avr/io.h 错误没有这样的文件或目录