用Poco:Condition唤醒两个线程

时间:2019-06-06 11:26:06

标签: c++ multithreading poco poco-libraries

在Windows 7(64位)下使用MSYS2中的Poco 1.9.0-1。

我有一个线程,发出3次Poco:Condition信号,睡眠时间为300毫秒。

我有两个线程使用两个不同的类EvListenerA和EvListenerB,它们从Poco :: Runnable扩展,并且它们正在等待相同的Poco :: Condition显示带有std :: cout的消息。

使用第一个和第二个信号没有问题,但是当启动第三个信号时,只有线程EvListenerA可以正确捕获它。

这是代码:

/*
 * main.cpp
 *
 *  Created on: 6 jun. 2019
 *      Author: ccortiz
 */

#include <Poco/Thread.h>
#include <Poco/Runnable.h>
#include <Poco/Condition.h>
#include <iostream>
using namespace std;

Poco::Condition condicion;
Poco::Mutex     mutex;

class GenEvents:public Poco::Runnable{
public:
    void run(){
        cout << "Launching GenEvents!" << endl;

        for (Poco::UInt32 i=0; i<3; i++){
            cout << "[GenEvents] Event_" << i << endl;
            condicion.broadcast();
            Poco::Thread::sleep(300); //Wait 300ms.
        }
        cout << "Ending GenEvents!" << endl;
    }
};

class EvListenerA:public Poco::Runnable{
public:
    void run(){
        cout << "Launching EvListenerA!" << endl;

        for (Poco::UInt32 i=0; i<3; i++){
            condicion.wait(mutex);
            cout << "   [EvListenerA] Receiving Event_" << i << endl;
        }
        cout << "Ending EvListenerA!" << endl;
    }
};

class EvListenerB:public Poco::Runnable{
public:
    void run(){
        cout << "Launching EvListenerB!" << endl;

        for (Poco::UInt32 i=0; i<3; i++){
            condicion.wait(mutex);
            cout << "   [EvListenerB] Receiving Event_" << i << endl;
        }
        cout << "Ending EvListenerB!" << endl;
    }
};

int main(void){
    Poco::Thread th1; //Hilo que genera 3 eventos.
    Poco::Thread th2; //Hilo que espera 3 eventos.
    Poco::Thread th3; //Hilo que espera 3 eventos.

    GenEvents  genEvents;  //Objeto que implementa el hilo generador de eventos.
    EvListenerA evListenerA; //Objeto que implementa el hilo receptor de eventos.
    EvListenerB evListenerB; //Objeto que implementa el hilo receptor de eventos.

    th2.start(evListenerA);
    th3.start(evListenerB);
    Poco::Thread::sleep(500); //Espera de medio segundo.

    th1.start(genEvents);

    th1.join();
    th2.join();
    th3.join();
}

这是程序输出:

Launching EvListenerB!
Launching EvListenerA!
Launching GenEvents!
[GenEvents] Event_0
   [EvListenerB] Receiving Event_0
   [EvListenerA] Receiving Event_0
[GenEvents] Event_1
   [EvListenerA] Receiving Event_1
   [EvListenerB] Receiving Event_1
[GenEvents] Event_2
   [EvListenerA] Receiving Event_2
Ending EvListenerA!
Ending GenEvents!

为什么我的输出中没有“ [[EvListenerB]正在接收事件_2”?

EvListenerB和Event_2会发生什么?

有什么主意吗?谢谢

1 个答案:

答案 0 :(得分:1)

嗯,对我来说,这是不确定的行为。参考文献明确指出ConditionMutexFastMutex一起使用。调用wait时必须锁定mutex! -它在您的代码中丢失。

来自reference的语录:

  

Condition对象始终与Mutex(或   FastMutex)对象。

  

解锁互斥锁(必须在调用wait()时将其锁定)并等待   在给定时间之前,一直到发出状态为止。

     

给定的互斥锁将在成功离开后再次锁定   功能,即使出现异常也是如此。

因此,如果您想查看所需的输出,则必须调用互斥锁上的锁定/解锁:

    for (Poco::UInt32 i=0; i<3; i++)
    {
        mutex.lock();  // <--- lock mutex
        condicion.wait(mutex);
        cout << "   [EvListenerA] Receiving Event_" << i << endl;
        mutex.unlock(); // <--- unlock
    }

EvListenerAEvListenerB类进行相同的更改。

首先,您要锁定互斥锁。然后调用wait,将其解锁mutex,我们一直等到发信号通知condition,然后wait返回并再次锁定互斥锁(从wait返回之前) )。在退出for循环迭代之前,将调用unlock