1

したがって、同じ変数「カウンター」を共有する2つのスレッドがあります。両方のスレッドがその時点に到達したら、実行を継続することでスレッドを同期したいと考えています。残念ながら、スレッドがチェック変数を変更していないため、デッドロック状態になります。私が持っている方法は次のとおりです。

volatile int counter = 0;

    Thread() {

             - some calculations - 

            counter++;
            while(counter != 2) {
               std::this_thread::yield();
            }
            counter = 0;

            - rest of the calculations -
    }

アイデアは、2 つのスレッドがあるため、それらがそのポイントに達すると (異なる時間に)、カウンターをインクリメントするということです。カウンターが 2 に等しくない場合、最初にそこに到達したスレッドは、他のスレッドがカウンターをインクリメントして同期されるまで待機する必要があります。ここで問題がどこにあるか知っている人はいますか?

この問題についてさらに詳しい情報を追加するために、配列に対する操作の半分を実行する 2 つのスレッドがあります。それらが完了したら、両方が計算を完了したことを確認したいと思います。それらが完了したら、プリンター スレッドに信号を送信してウェイクアップし、配列の印刷とクリアの操作を実行できます。両方のスレッドが完了する前にこれを行うと、問題が発生します。

擬似コード:

Thread() {

    getLock()
    1/2 of the calculations on array
    releaseLock()

    wait for both to finish - this is the issue

    wake up printer thread

}
4

3 に答える 3

2

このような状況では、アトミック カウンターを使用する必要があります。

std::atomic_uint counter = 0;

与えられた例では、初期化された兆候もありませんcounter

于 2015-11-08T04:50:44.707 に答える
1

あなたはおそらく探しているでしょうstd::conditional_variable:条件変数は、あるスレッドが別のスレッドにシグナルを送ることを可能にします。カウンターを使用しているようには見えず、同期にのみ使用しているように見えるため、別の回答からのコードをいくつか示します(免責事項: これは私の回答の 1 つです) std::conditional_variable。異なるスレッドでの処理ロジックと同期の実行を示しています。値の周り:

unsigned int accountAmount;
std::mutex mx;
std::condition_variable cv;

void depositMoney()
{
    // go to the bank etc...
    // wait in line...
    {
        std::unique_lock<std::mutex> lock(mx);
        std::cout << "Depositing money" << std::endl;
        accountAmount += 5000;
    }
    // Notify others we're finished
    cv.notify_all();
}
void withdrawMoney()
{
    std::unique_lock<std::mutex> lock(mx);
    // Wait until we know the money is there
    cv.wait(lock);
    std::cout << "Withdrawing money" << std::endl;
    accountAmount -= 2000;
}
int main()
{
    accountAmount = 0;
    // Run both threads simultaneously:
    std::thread deposit(&depositMoney);
    std::thread withdraw(&withdrawMoney);
    // Wait for both threads to finish
    deposit.join();
    withdraw.join();
    std::cout << "All transactions processed. Final amount: " << accountAmount << std::endl;
    return 0;
}
于 2015-11-08T05:01:40.647 に答える
0

カウントダウンラッチの使用を検討します。アイデアは、目的の操作が完了するまで 1 つ以上のスレッドをブロックすることです。この場合、両方のスレッドが配列の変更を完了するまで待ちます。

簡単な例を次に示します。

#include <condition_variable>
#include <mutex>
#include <thread>

class countdown_latch
{
public:
    countdown_latch(int count)
        : count_(count)
    {
    }

    void wait()
    {
        std::unique_lock<std::mutex> lock(mutex_);
        while (count_ > 0)
            condition_variable_.wait(lock);
    }

    void countdown()
    {
        std::lock_guard<std::mutex> lock(mutex_);
        --count_;
        if (count_ == 0)
            condition_variable_.notify_all();
    }

private:
    int count_;
    std::mutex mutex_;
    std::condition_variable condition_variable_;
};

使用法は次のようになります

std::atomic<int> result = 0;
countdown_latch latch(2);

void perform_work()
{
    ++result;
    latch.countdown();
}

int main() 
{
    std::thread t1(perform_work);
    std::thread t2(perform_work);

    latch.wait();

    std::cout << "result = " << result;

    t1.join();
    t2.join();
}
于 2015-11-08T06:02:31.600 に答える