2

以下のコードでは、私の関数はデータ エントリをディスクに書き込み、エントリが記録されているファイルにオフセットを返すことになっています。ただし、複数のスレッドでコードを実行すると、この値が正確でないことがあります。このコードにスレッド セーフの問題はありますか?

// 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; 
}
4

2 に答える 2

2

おそらく、問題は fopen マニュアルに記載されている動作に関連している可能性があります。

ANSI C では、入力操作がファイルの終わりに達しない限り、出力と入力の間にファイル ポジショニング関数が介入する必要があることに注意してください。(この条件が満たされない場合、読み取りは、最新以外の書き込みの結果を返すことが許可されます。) したがって、fseek(3) または fgetpos(3) を配置することをお勧めします (Linux では実際に必要な場合もあります)。 ) このようなストリームでの書き込み操作と読み取り操作の間の操作。この操作は、(fseek(..., 0L, SEEK_CUR) のように) 同期の副作用のために呼び出される明らかなノーオペレーションである可能性があります。

ftell は、読み取り操作として扱われる可能性があります。ftell の前に fseek(..., 0L, SEEK_CUR) を挿入してみて、それが役立つかどうかを確認してください。

于 2012-07-02T20:00:25.327 に答える
0

ファイルを開く前にロックしていないため、スレッドセーフではありません。

他のプロセスが I/O 用にファイルを開く可能性があり、予期しない結果を招く可能性がありました。

于 2012-07-02T18:11:56.790 に答える