1

Thread SynchronizationUnix環境でのAdvance Programmingという本 を読んでいます。

このセクションでは、動的に割り当てられたオブジェクトでミューテックスを使用する例を示します。私も同じように疑問を持っています。

ここで、私の疑問を説明するために起こっているイベントのタイムライン(上から下) を共有しています。

  1. スレッド 1 が作成されました。
  2. Thread1 はミューテックス変数を作成し、それを初期化し、グローバル リストに配置して、他のユーザーが使用できるようにします。
  3. ここで、Thread1 は共有データ構造を使用するためにロックを取得しましたds。スレッド 1 は で非常に大量の作業を行う必要がありますds。つまり、スレッド 1 はこのロックを長時間取得します。
  4. Thread1 がまだロックを取得している間に、Thread2 が作成されます。
  5. 現在、Thread2 も ds を使用したいと考えています。
  6. そのため、Thread2 はまず、ds への参照が増加したことを示すカウンターをインクリメントする必要があります。これを行うには(本によると)mutex_t、カウントをインクリメントする前に 、まず同じ変数を使用してロックを取得する必要があります。
  7. ただし、Thread1 は既にこのmutex_t変数のロックを取得しているためlock()、カウントをインクリメントする前に Thread2 を呼び出すと、Thread1 がロックを解除するまで待機する必要があります。

疑問:

  1. 彼が話しているグローバルリストについて(リストを作成し、その参照をすべてのスレッドまたは特定のリストに渡すことを意味します)
  2. Thread1 がロック変数を作成すると、カウントが 1 に設定されます。その後、Thread2 は、このカウントを 2 にインクリメントするのを待っています。しかし、現在の作業を行った後、Thread1 が ds を使用する必要がなかった状況を想定します。foo_rele()したがって、ロックを解除する前にカウントを減らすか、最初にロックを解除してから再度ロックを呼び出してカウントを減らします。Thread2 がカウントをインクリメントする前に、Thread1 がカウントをデクリメントする可能性があります。はいの場合 (私によると)、私のデータ構造は破棄されますか? したがって、この本の例にはわずかな誤りがあると思います。別の mutex_var を使用してカウントをインクリメントした方がよいでしょうか?
4

3 に答える 3

2

そうです、例11.10は、構造foo内のコンテンツに関するものです。各構造にはロックがあるため、スレッド1がオブジェクトを操作するには、スレッド1がオブジェクト内にミューテックスを保持する必要があります。

与えられた例は不完全であり、私はあなたの混乱を理解することができます。foo_releは、スレッドがそのオブジェクトを必要としなくなるまで呼び出されることは想定されていません。別のスレッドがfooを使用したい場合は、foo_hold()を呼び出して参照カウントをインクリメントすることになっています(fp-> count ++)。そして、はい、スレッド2がそれを取得したいと思う可能性があり、スレッド1がそれを解放している競合状態があります。

これは、多脅威プログラミングでは間違いなく珍しいことではありません。コードがそれを回避するように特別に記述されていない限り、スレッドはスレッドで作業したいものを削除する可能性があります。回避には、たとえば、オブジェクトのリストのロックが含まれ、私のスレッドがリストロックを保持している場合、他のスレッドはリストに物を追加または削除できません(リストを検索するべきではありません。何かを追加または削除しているだけかもしれませんが、リストに一貫性があるという保証はありません)。

これがお役に立てば幸いです。

于 2012-12-29T12:15:28.143 に答える
2
  1. スレッドはメモリを共有するため、同じプロセス内のすべてのスレッドでグローバル変数を参照できます (したがって、各スレッドにポインターを渡す必要はありません)。

  2. ミューテックスを使用する場合は、スレッドが任意の順序でミューテックスをロックできるという事実を考慮に入れる必要があります (POSIX は特定の順序を保証しません)。したがって、他のスレッドがミューテックスへのアクセスを取得する前に、スレッド 1 が構造を作成、使用、および破棄する可能性は十分にあります。

PS私はあなたの疑問を理解しています。コード スニペットで実際に欠けているのは、構造体への同時書き込みを実際に防止している他のミューテックスです。

于 2012-12-29T12:36:39.237 に答える
2

A. 「グローバル リスト」という用語の下で、作成者はスレッド間で共有されるすべての変数を理解していると思います。

例:

struct foo* shared_foo; /* This pointer is shared between all threads */

struct foo* foo_alloc(void)
{
   /* This pointer is local to the thread which allocates the memory */
   struct foo *fp;

    if ((fp = malloc(sizeof(struct foo))) != NULL) {
        /* whatever */
    }
    /* local pointer value returned */
    return(fp);
}

/* probably somewhere in the code the shared pointer (on the 'global list') is initialized this way */
shared_foo = foo_alloc();

B.うーん...私はあなたの言うことをよく理解していません。あなたのシナリオをリストとして書いていただけますか?私の意見f_countでは、初期化中に「このミューテックスは使用中です」というフラグとして設定されます。そのため、mutex が解放されると、f_count値は 1 に設定されます。Thread1がロックを取得すると、値は 2 に設定されます。ロックを解放すると、値は 1 に戻されます。有効なf_count値は、1 (初期化および解放) および 2 です。 (初期化されビジー)。ミューテックスを解放するには、foo_rele取得されたときに 2 回 ( f_count= 2)、解放されたときに 1 回 ( f_count= 1) 呼び出すだけです。その後、f_count値が 0 になり、mutex が削除されます。

于 2012-12-29T12:02:36.337 に答える