2012-10-02 2 views
8

によって引き起こされるスレッド不足私は2つのスレッド、タイトなループで動作するもの、そして時折最初に同期を実行する必要のある他のを持っていますスレッド2は、ロックを取ることによって、事実上スレッド1を一時停止し、必要な同期を実行することができるということである。スレッド1は、ロックを解除することによって一時停止することができ、スレッド2がロックを待っていない場合は、再ロックして作業に戻ることができます。のpthread:</p> <pre><code>// thread 1 while(1) { lock(work); // perform work unlock(work); } // thread 2 while(1) { // unrelated work that takes a while lock(work); // synchronizing step unlock(work); } </code></pre> <p>私の意図:迅速な再ロック

私が遭遇した問題は、mutexesが公平でないことです。つまり、スレッド1はすぐにmutexを再ロックし、スレッド2を飢えさせます。pthread_yieldを使用しようとしましたが、これまでは大丈夫ですが、すべてのシステム/コア数で動作することを確認してください。マルチコアシステムであっても、スレッド1が常にスレッド2になることを保証する方法はありますか?

この同期プロセスを処理する最も効果的な方法は何ですか?

+0

条件変数を使用して、スレッド2が優先順位を高くし、次にスレッド1を達成する方法の1つにしたい場合、質問に記載されていることは公平性とは関係ありません。 – Michael

+0

この質問は[*フェアクリティカルセクション(Linux)*](http://stackoverflow.com/q/6449732/134633)と非常によく似ています。 – caf

答えて

3

:スキームのこの種の下で

#include <pthread.h> 

typedef struct ticket_lock { 
    pthread_cond_t cond; 
    pthread_mutex_t mutex; 
    unsigned long queue_head, queue_tail; 
} ticket_lock_t; 

#define TICKET_LOCK_INITIALIZER { PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER } 

void ticket_lock(ticket_lock_t *ticket) 
{ 
    unsigned long queue_me; 

    pthread_mutex_lock(&ticket->mutex); 
    queue_me = ticket->queue_tail++; 
    while (queue_me != ticket->queue_head) 
    { 
     pthread_cond_wait(&ticket->cond, &ticket->mutex); 
    } 
    pthread_mutex_unlock(&ticket->mutex); 
} 

void ticket_unlock(ticket_lock_t *ticket) 
{ 
    pthread_mutex_lock(&ticket->mutex); 
    ticket->queue_head++; 
    pthread_cond_broadcast(&ticket->cond); 
    pthread_mutex_unlock(&ticket->mutex); 
} 

、何の低レベルのpthreadミューテックスはスレッドが内にある間保持されていませんticketlock protected Criticalセクションで、他のスレッドがキューに参加できるようにします。

5

場合によっては、awakeを実行して必要な操作をすべて実行する必要がある場合には、condition variableを使用して2番目のスレッドに通知することをお勧めします。

+1

また、これらの問題の潜在的な解決策としてセマフォーについて言及してください、彼らはしばしば見落とされます! –

+0

この問題にどのようにセマフォーを使用できるかについての例やスニペットはありますか? – Atanu

+0

先入先出チケットロックを実装するためにpthreads条件変数を使用する方法を示しているところで、この回答を参考にすると便利です(http://stackoverflow.com/a/6453925/134633)。 – caf

2

pthreadは、そのAPIにスレッド優先度という概念を提供します。 2つのスレッドがミューテックス上で競合する場合、スケジューリングポリシーは、どのスレッドがそれを取得するかを決定します。関数pthread_attr_setschedpolicyはそれを設定し、pthread_attr_getschedpolicyは情報の取得を許可します。今

悪いニュース:

  • のみ2つのスレッドがミューテックスをロック/ロック解除されて、私は競争の任意の並べ替えを見ることができない、アトミック命令を実行する最初の人は、他のブロックを、それを取ります。この属性がここに適用されるかどうかはわかりません。関数は異なるパラメータ(SCHED_FIFOSCHED_RRSCHED_OTHERSCHED_SPORADIC)が、in this questionを取ることができ
  • 、私がいた場合

は、だから私はそれに打撃を与えるだろう)のみSCHED_OTHERは、Linux上でサポートされていたと回答してきましたあなたは、あまり期待していません。 pthread_yieldは私にとってより有望なようです。詳細情報はhereです。あなたはこれらの線に沿って、pthreadsのミューテックスの上にFIFO「チケットロック」を構築することができます

0

上記のチケットロックは最高のようです。ただし、pthread_yieldが機能するようにするには、boolが待機していることがあります。これはthread2によって設定され、リセットされます。 thread1は、ブール待機が設定されている限り、発生します。

0

ここには、あなたのケース(2つのスレッド)で動作する簡単な解決策があります。 std::mutexを使用している場合、このクラスはドロップインの代替品です。ミューテックスをこのタイプに変更すると、あるスレッドがロックを保持し、他のスレッドがそのスレッドを待機している場合、最初のスレッドのロックが解除されると、2番目のスレッドはロックを取得してから再びロックできます。

mutexを同時に使用するスレッドが2つ以上発生しても、それらは同時に機能しますが、公平性は保証されません。

平文pthread_mutex_tを使用している場合は、この例に従ってロックコードを簡単に変更できます(ロック解除は変更されません)。

#include <mutex> 

// Behaves the same as std::mutex but guarantees fairness as long as 
// up to two threads are using (holding/waiting on) it. 
// When one thread unlocks the mutex while another is waiting on it, 
// the other is guaranteed to run before the first thread can lock it again. 

class FairDualMutex : public std::mutex { 
public: 
    void lock() { 
     _fairness_mutex.lock(); 
     std::mutex::lock(); 
     _fairness_mutex.unlock(); 
    } 
private: 
    std::mutex _fairness_mutex; 
}; 
関連する問題