2009-06-10 9 views
2

のLinuxboost::interprocess::shared_memory_objectを使用してIPCを実行しています(匿名ミューテックスの例)。boost :: interprocess :: scoped_lockを保持している間スリープすると、決して解放されません。

shared_memory_objectを作成して書き込みを行うサーバプロセスがあり、interprocess_mutexscoped_lockにラップしています。もう一方が書いたものを印刷するクライアントプロセス - この場合、それはintです。

私は問題に遭遇しました。サーバがミューテックスを保持している間スリープした場合、クライアントプロセスは決してそれを取得できず、永遠に待ちます。

バギーサーバーループ:

using namespace boost::interprocess; 
int n = 0; 
while (1) { 
    std::cerr << "acquiring mutex... "; 
    { 
     // "data" is a struct on the shared mem. and contains a mutex and an int 
     scoped_lock<interprocess_mutex> lock(data->mutex); 
     data->a = n++; 
     std::cerr << n << std::endl; 
     sleep(1); 
    } // if this bracket is placed before "sleep", everything works 
} 

サーバー出力:

acquiring mutex... 1 
acquiring mutex... 2 
acquiring mutex... 3 
acquiring mutex... 4 

クライアントループ:

while(1) { 
    std::cerr << "acquiring mutex... "; 
    { 
     scoped_lock<interprocess_mutex> lock(data->mutex); 
     std::cerr << data->a << std::endl; 
    } 
    sleep(1); 
} 

クライアント出力は(永遠に待つ):

acquiring mutex... 

事は、私がsleep呼び出しの前の行にブラケットを移動した場合、すべてが動作します、です。どうして?ロックされたミューテックスでスリープ状態になると、ミューテックスが永久にロックされるとは思わなかった。

カーネルがサーバプロセスを起動すると、スコープは終了し、mutexは解放されますが、待機プロセスには実行の機会は与えられません。その後、サーバーはロックを再度取得します...しかし、それは意味をなさないと思われます。

ありがとうございます!

答えて

7

あなたの理論は正しいです。

あなたがリンクを参照して、匿名のミューテックス例の下を見ると、私たちが見ることができるように、あなたは

を参照してくださいよ、ミューテックスは、データを保護するために有用であるが、他のプロセスに通知しませんイベント。

ミューテックスを解放しても、それを待っている他の人には通知されず、プロセスが起きたばかりであるため、スケジューリングの量が増えて作業が増えます。クライアントがmutex自体を取得しなければならない最初の機会である、再びスリープする前にループし、mutexを再取得します。

sleep()をスコープ外に移動すると、mutexが空いている間にスリープ状態になり、クライアントがmutexを実行して取得する機会が与えられます。

プロセッサをあきらめたいが、スコープ内でスリープ状態にしたい場合は、sched_yield()(Linuxのみ)に電話してみてください。sleep(0)も動作する可能性があります。

+0

ブーストはスレッドをあきらめて(Linuxのschedu_yieldのように)呼び出すことができます:boost :: this_thread :: yield() – teeks99

+0

ありがとう。 'sleep(0)'はうまく動作し、その理論を確認します。私はミューテックスをリリースするという行為は少なくともシステムコールとそれに伴う再スケジューリングを引き起こすという印象を受けましたが、私は間違っていました。 –

0

mutexを保持している間にスリープ状態が間違っています。ミューテックスはいくつかのデータ(すなわち、data-> a)を保護し、そのデータの読み取り/書き込みに関してスコープを最小限に抑える必要があります。

+0

はい、わかりました、ありがとうございます。しかし、それはとにかく動作してはいけませんか? –

+0

私はそれが実際にすべきだと思った。本当の問題をスティーブがよりよく理解したように思える。 – Andrey

関連する問題