1

私は、中間処理スレッドを使用して生産者と消費者の問題に取り組んでいます。これらのアプリケーションを 200 実行すると、多数の接続がタイムアウトになると、win7 でシステムがロックされます。残念ながら、デバッグ方法を知っている方法ではありません。システムが応答しなくなり、電源ボタンで再起動する必要があります。私のMacでは問題なく動作し、奇妙なことに、セーフモードのWindowsでも問題なく動作します。

ホストアプリケーションが使用するブースト1.44を使用しています。

これが私のキューです。私の意図は、キューがそのサイズで同期されることです。これを操作してtimed_wait、通知が失われていないことを確認しましたが、効果に違いはありませんでした.

class ConcurrentQueue {
public:
    void push(const std::string& str, size_t notify_size, size_t max_size);
    std::string pop();

private:
    std::queue<std::string> queue;
    boost::mutex mutex;
    boost::condition_variable cond;
};

void ConcurrentQueue::push(
  const std::string& str, size_t notify_size, size_t max_size) {
    size_t queue_size;
    {{
        boost::mutex::scoped_lock lock(mutex);
        if (queue.size() < max_size) {
            queue.push(str);
        }
        queue_size = queue.size();
    }}
    if (queue_size >= notify_size)
        cond.notify_one();
}

std::string ConcurrentQueue::pop() {
    boost::mutex::scoped_lock lock(mutex);
    while (!queue.size())
        cond.wait(lock);
    std::string str = queue.front();
    queue.pop();
    return str;
}

これらのスレッドは、以下のキューを使用して処理し、libcurl を使用して送信します。

boost::shared_ptr<ConcurrentQueue> queue_a(new ConcurrentQueue);
boost::shared_ptr<ConcurrentQueue> queue_b(new ConcurrentQueue);

void prod_run(size_t iterations) {
    try {
        // stagger startup
        boost::this_thread::sleep(
              boost::posix_time::seconds(random_num(0, 25)));
        size_t save_frequency = random_num(41, 97);
        for (size_t i = 0; i < iterations; i++) {
            // compute
            size_t v = 1;
            for (size_t j = 2; j < (i % 7890) + 4567; j++) {
                v *= j;
                v = std::max(v % 39484, v % 85783);
            }
            // save
            if (i % save_frequency == 0) {
                std::string iv = 
                              boost::str( boost::format("%1%=%2%") % i % v );
                queue_a->push(iv, 1, 200);
            }
            sleep_frame();
        }
    } catch (boost::thread_interrupted&) {
    }
}

void prodcons_run() {
    try {
        for (;;) {
            std::string iv = queue_a->pop();
            queue_b->push(iv, 1, 200);
        }
    } catch (boost::thread_interrupted&) {
    }
}

void cons_run() {
    try {
        for (;;) {
            std::string iv = queue_b->pop();
            send_http_post("http://127.0.0.1", iv);
        }
    } catch (boost::thread_interrupted&) {
    }
}

この方法でミューテックスを使用することについての私の理解は、システムを応答不能にするべきではありません。どちらかといえば、私のアプリはデッドロックし、永久にスリープ状態になります。

これらを一度に 200 個使用すると、そうでないシナリオが作成される方法はありますか?

アップデート:

コンピュータを再起動すると、ほとんどの場合、USB キーボードを再接続して応答させる必要があります。ドライバーのコメントを考えると、それは関係があるかもしれないと思いました。ノースブリッジドライバーは最新のものでしたが、更新してみました。注意が必要な他のドライバーがないかどうかを確認します。

アップデート:

私はメモリ、非ページ プール、CPU、ハンドル、ポートを監視しましたが、システムが応答している間はいつでも異常な速さではありません。私には見えませんが、最後に何かが急上昇する可能性があります。

アップデート:

システムがハングすると、レンダリングが停止し、キーボードに反応しなくなります。ただし、レンダリングされた最後のフレームはそのままです。システムはまだ動作しているように聞こえますが、システムが再起動しても、イベント ビューアーにはクラッシュしたというメッセージは表示されません。クラッシュ ダンプ ファイルもありません。これは、OS の実行がブロックされていると解釈します。

4

1 に答える 1

1

ミューテックス ロックは、同じロックを使用する他のアプリケーションをロックします。OS によって使用されるミューテックスは、どのアプリケーションからも (直接) 利用可能であってはなりません。

もちろん、ミューテックスが何らかの方法で OS を使用して実装されている場合、OS を呼び出して CPU リソースを使用する可能性があります。ただし、ミューテックス ロックによって、アプリケーションが CPU リソースを他の方法で使用するよりも悪い動作が発生することはありません。

もちろん、不適切な方法でロックを使用すると、関数 1 がロック A を取得し、次に関数 2 がロック B を取得するため、アプリケーションのさまざまな部分がデッドロックになる可能性があります。関数 1 がロック B を取得しようとすると、関数2 がそれぞれのロックを解放する前にロック A を取得しようとすると、デッドロックが発生します。ここでのコツは、常に複数のロックを同じ順序で取得することです。したがって、同時に 2 つのロックが必要な場合は、常に最初にロック A を取得し、次にロック B を取得します。

デッドロックインは OS 自体に影響を与えるべきではありません - どちらかといえば改善されますが、デッドロックの場合にアプリケーションが何らかの形で「誤動作」している場合、OS を何度も呼び出すことで問題が発生する可能性があります - たとえば、ロックがによって行われ:

while (!trylock(lock))
{
      /// do nothing here
}

システム使用率のピークを引き起こす可能性があります。

于 2013-02-18T18:37:30.240 に答える