2017-04-12 8 views
0

私は私が個人的に実装したデータ構造を持っています。これは現在、複数のスレッドにわたって使用する必要があります。簡単にするためにC - 私のデータ構造の実装を同期させるには?

typedef struct 
{ 
    void** array_of_elements; 
    size_t size; 
} myStruct; 

、のは私のデータ構造は、これらの機能を持っているとしましょう:

// Gets a data element from the structure. 
void* get(myStruct *x); 
// Prints out all the data elements. 
void print(myStruct *x); 
// Adds an element into the structure. 
void add(myStruct *x, void *to_be_added); 

彼らは両方のアクセサであるため、別のスレッドがprintを呼び出している間、それはgetを呼び出すために全く問題はありません。ただし、addが現在呼び出されている間は、getprintは機能しません。逆の場合、は、getprintが現在進行中の場合には機能しません。

だから私は、次のように見えるようにmyStructを変更:

typedef struct 
{ 
    void** array_of_elements; 
    size_t size; 

    // True when a mutator is editing this struct. 
    bool mutating; 
    // The number of threads currently accessing this struct. 
    int accessors; 
} myStruct; 

私の関数は次のようになり今:

void* get(myStruct *x) 
{ 
    // Wait for mutating to end. 
    while (x->mutating); 
    // Indicate that another accessor is now using this struct. 
    x->accessors++; 

    // get algorithm goes here 

    // Declare we are finished reading. 
    x->accessors--; 

    return ... 
} 

// Same as above... 
void print(myStruct *x) 
... 

void add(myStruct *x) 
{ 
    // Wait for any accessors or mutators to finish. 
    while (x->mutating || x->accessors > 0);  
    x->mutating = true; 

    // add algorithm here 

    x->mutating = false; 
} 

しかし、私はこれで問題がたくさんあると思います私はそれらを解決する方法を見つけることができません:

  • 私の同級生の一人が、このようなループを使って私に教えてくれました。
  • キューの意味がありません。 myStructの使用が完了するのを待っている最初の方法は、必ずしも次に進む方法ではありません。
  • スレッドが次に進むキューデータ構造があったとしても、データ構造も同期させる必要があるそれ自体は、同期データ構造を必要とする無限ループであるです。
  • 私はそれは同じナノ秒に1つのスレッドが(彼らは読書を開始したいという意味)0から1accessorsカウンタを変更し、それが0で、変異開始値です見にミューテータスレッドのために可能だということも可能だと思います。次に、ミューテータスレッドとアクセサスレッドの両方が同時に実行されます。
  • 私はこのロジックがグリッドロック(互いに無限に待っているスレッド)を引き起こす可能性があると確信しています。
  • 私は特定のスレッドを覚醒させる方法を知らず、whileループに詰め込まれているだけでなく、このタスクに必要なときに目を覚まします。
+0

読み書きロックを調べてみてください... – Dmitri

+0

@Dmitri私は実際の実装がどのように見えるのかを遠隔で読み書きするためのロックを持っていませんか? – Hatefiend

+0

スレッド間で変数を共有する場合は、アトミックアクセスやmutexのような何らかの同期メカニズムを使用する必要があります。読取り/書込みロックは、複数のスレッドで読取りを許可するが、書込みには排他アクセスを必要とすることを除いて、mutexと似ています。 posixスレッドの場合、 'pthread_rwlock_t'があり、ウィンドウには"スリムなリーダーライターロック "があります。 – Dmitri

答えて

0

あなたは正しいアイデアを持っています。間違ったアプローチです。どのOSをプログラミングしているのかよく分かりませんが、あなたがしたいことをするにはmutexまたはsemaphoreという概念を見たいと思っています。対応POSIXでのLinux/Unixでは

、あなたはpthreadsのを見ることができます:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx

http://www.cs.wm.edu/wmpthreads.html

はWindowsでは、あなたはmutex概念に近いもののためにCritical Sectionsを見ることができます

またはWaitForMultipleObjectsに近いものについてsemaphore

https://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx

そして、whileループを使用することは悪い考えです。この場合、ビジー・ループと呼ばれるものを使用しています。ここでもっと読み:mutexまたはsemaphoreを使用して

What is a busy loop?

、何のwhileループは必要ありません。がんばろう!

+0

実装はライブラリに依存していますか?それは正しいとは思わない。私は私の 'struct'の内部を考えました。私の' struct' **はmutex **なので、スレッドをロックするためにいくつかの変数を追加する必要がありますか? – Hatefiend

+0

私には言いたいことがあります:スレッドライブラリを使用せずにこれを行う方法はありますか?私の構造を使用する開発者は、私が設計したオペレーティングシステム上にないかもしれません。だから代わりに、 'struct'を使用するのが安全かどうかを指定する' struct'の中に変数を持たせることができますか? – Hatefiend

+0

@Hatefiendコードを特定のスレッドAPIに結びつけたくない場合は、独自の一回限りのミューテックスまたは読み書きロックを実装するのではなく、ロックをユーザーに任せておく方がよいでしょう。あなたが期待するよりも正しく行うことがより困難になります)。彼らがしなければならないことは、自分の選択したロックを取得/解放することです(おそらく、使用しているスレッドの実装に関係なく、アクセス関数を呼び出す前後に)。 – Dmitri

関連する問題