1

PRINT マクロのスレッド セーフについて疑問に思っていたので、自分の状況でのファイル操作がスレッド セーフかどうかを確認するプログラムを作成したので、fn0 にスリープを追加したところ、スレッド セーフであることがわかりました。

$cat t
fn1
fn0

両方を印刷し、上書きしません。

テストは十分ですか、それとも他の状況はありますか PS : ファイル ポインターを共有していませんが、順序付けには満足しています (順序付けされていない/順序付けされていないことは問題ありません)。

- - - - - -大きい - - - - - - -

#define PRINT(args ...) if (logflag) { \
FILE *flog = fopen(LOGFILE, "a"); \
fprintf( flog, args); \
fclose(flog); \
}  fprintf(stderr, args); fflush(stderr);

-------------------テストプログラム--------------------------------

#include <stdio.h>
#include <pthread.h>

#define LOGFILE "t"
char c='1';
void *fn0(void* v)
{

    FILE *flog = fopen(LOGFILE, "a");
    //sleep(2);
    fprintf( flog,"%s\n", "fn0");
    fclose(flog);

    printf ("Enter value ");
    c=getchar();
}

void* fn1(void*v)
{
    FILE *flog = fopen(LOGFILE, "a");
    fprintf( flog,"%s\n", "fn1");
    fclose(flog);
}
int main()
{
    pthread_t t0;
    pthread_t t1;


    pthread_create(&t0, NULL, fn0, (void *) NULL);
    pthread_create(&t1, NULL, fn1, (void *) NULL);
    pthread_join(t1, NULL);
    pthread_join(t0, NULL);

    return 0;
}
4

2 に答える 2

3

あなたのコードはスレッドセーフではありません。スレッドの 1 つがファイルを開こうとしているときに、別のスレッドがファイルを開こうとすると、2 回目の開こうとすると共有違反で失敗する可能性があります。OS がファイルを同時に 2 回開くことを許可している場合でも、2 つの別個の非同期バッファーと 2 つの別個のファイル ポインターが存在することになります。書き込みが一貫しているという保証はまったくありません。

ミューテックスを使用して、共有リソースへのアクセスをシリアル化する必要があります。

または、プロデューサー/コンシューマー アプローチを使用して、ログへのすべての書き込みを単一のスレッド (コンシューマー) に置きます。次に、複数のプロデューサー スレッドがロギング タスクをコンシューマー スレッドにプッシュできるようにします。

于 2013-02-13T01:33:40.010 に答える
2

そのコードは、スレッドセーフにかなり近づいています。次のことを行わないという事実により、確かにスレッドセーフです。

  • プロセスメモリを破壊する
  • インメモリデータ構造への同時アクセスによるセグメンテーション違反につながります。
  • 部分的に書き込まれたデータの読み取りにつながる (あるスレッドでバッファーを埋め、同時に別のスレッドで読み取るなど)

ただし、David Heffeman が述べたように、ファイルへの書き込みレベルではスレッドセーフではありません。近いですけどね。fopen + fwrite の代わりに open + write を使用するなど、バッファリングされた IO の代わりに書き込みにシステム コールを使用すると、アトミックな書き込みとスレッド セーフを実現できます。

書き込みがアトミックであることを確認する方法の詳細については、この回答を参照してください: Is file append atomic in UNIX?

もう1つ。global の使用char cは危険ですが、示されているコンテキストではスレッドセーフです。cが関数内で宣言されている場合、fn0潜在的な問題が解消されます (自動変数が保持され、宣言されていない限りstatic)。

このようなケースのテストのトピックについて言えば、私の経験では、ストレス テストは信頼できる結果をもたらすことができますが、ストレス テストにはある程度の努力が必要です。圧倒的でイライラします。ストレステストを行うには、構成可能な回数の繰り返しで構成可能な数のスレッドをスピンオフするプログラムをセットアップするだけです。このようなテストでは、20 スレッドと 1000 回の反復から始めることをお勧めします。

そうは言っても、テストだけではスレッドセーフと競合状態が存在しないことを 100% 証明できないことに同意します。

于 2013-08-26T20:12:07.243 に答える