使用条件变量从不同的线程打印偶数和奇数

时间:2016-05-01 08:42:13

标签: multithreading c++11

我试图像1,2,3,4,5,6,7那样打印.....但是来自两个不同线程的偶数和奇数。另外我想用条件变量来制作这个程序。 我创建了以下程序,它只打印奇数部分并挂起(可能是死锁......我不知道)。 请告诉我实施中的问题。

#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#define MAX 25
using namespace std;

mutex mu;
condition_variable cv;

void printodd()
{
    for (size_t i = 0; i < MAX; i++)
    {
        if (i % 2 != 0)
        {
            unique_lock<mutex> locker(mu);
            cout <<"Odd : "<< i << endl;
            locker.unlock();
            cv.notify_one();
        }
    }
}

void printeven()
{
    for (size_t i = 0; i < MAX; i++)
    {
        if (i % 2 == 0)
        {
            unique_lock<mutex> locker(mu);
            cv.wait(locker);
            cout <<"Even : "<< i << endl;
            locker.unlock();
        }
    }
}

int main()
{
    thread th1(printodd);
    thread th2(printeven);
    th1.join();
    th2.join();
    getchar();
}

3 个答案:

答案 0 :(得分:1)

因为通知没有排队。这意味着如果调用notify_one()且当前没有等待的线程,则此通知将丢失。您看到1,2,3,4,5,6,7,.....,因为第一个线程的完成速度比第二个线程的启动速度要快。第二个线程启动后,它立即进入等待状态,永远持续(死锁)。

不仅如此,即使通知排队(低位),您也会首先从第一个线程看到1,而第二个线程只看到0(在它收到通知之后)

您需要创建两个互斥锁/条件变量(每个线程一个)并从主线程调用第一个通知。

答案 1 :(得分:1)

我在分析问题原因(缺少通知排队)时同意其他答案,但不同意需要两个同步对象实例。

您的问题是生产者 - 消费者队列之一,生产者和消费者交替每次迭代。对于生产者消费者队列,单个互斥和条件就足够了。对您的代码进行以下微小修改使其工作:

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


    #define MAX 25
    using namespace std;


    mutex mu;
    condition_variable cv;
    bool even = true;

    void print_it(int k)
    {
        const auto is_even = k % 2 == 0;
        for (size_t i = 0; i < MAX; i++)
        {
            if (i % 2 == k)
            {
                unique_lock<mutex> locker(mu);
                cv.wait(locker, [is_even](){return even == is_even;});
                cout <<": "<< i << endl;
                even = !even;
                locker.unlock();
                cv.notify_one();
            }
        }
    }

    int main()
    {
        thread th0(print_it, 0);
        thread th1(print_it, 1);
        th0.join();
        th1.join();
    }

答案 2 :(得分:0)

您将需要两个条件变量:一个用于奇数,一个用于偶数。

每个线程必须等待它自己的条件,一旦该线程可用,打印它自己的下一个数字,然后通过那个条件变量通知另一个线程并等待另一个线程再次解锁一个人完成了它的工作。

为了开始,&#34;奇怪&#34;在创建线程之后必须通知条件变量一次以打印第一个&#34; one&#34;。