使用 Poco:Condition 唤醒两个线程
Waking-up two threads with a Poco:Condition
在 Windows 7(64 位)下使用来自 MSYS2 的 Poco 1.9.0-1。
我有一个线程,发出三次 Poco:Condition 信号,休眠 300 毫秒。
我有两个线程使用两个不同的 类 EvListenerA 和 EvListenerB,它们从 Poco::Runnable 扩展而来,并且它们正在等待相同的 Poco::Condition 以显示带有 [=34= 的消息].
对于第一个和第二个信号,没有问题,但是当第三个信号启动时,只有线程 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] Receiving Event_2”?
EvListenerB 和 Event_2 发生了什么?
有什么想法吗?谢谢
嗯,对我来说这是未定义的行为。参考文献中明确指出 Condition
与 Mutex
或 FastMutex
一起使用。当wait
被调用时mutex
必须被锁定! - 您的代码中缺少它。
引用自reference:
A Condition object is always used in conjunction with a Mutex (or
FastMutex) object.
和
Unlocks the mutex (which must be locked upon calling wait()) and waits
for the given time until the Condition is signalled.
The given mutex will be locked again upon successfully leaving the
function, even in case of an exception.
所以如果你想看到期望的输出,你必须调用 lock/unlock 到 mutex:
for (Poco::UInt32 i=0; i<3; i++)
{
mutex.lock(); // <--- lock mutex
condicion.wait(mutex);
cout << " [EvListenerA] Receiving Event_" << i << endl;
mutex.unlock(); // <--- unlock
}
对 EvListenerA
和 EvListenerB
类 进行相同的更改。
首先你要锁定互斥体。然后 wait
被调用,它解锁 mutex
并且我们等待直到 condition
发出信号,然后 wait
returns 并且互斥锁再次被锁定(在从 [ 返回之前=14=]).在离开 for 循环迭代的范围之前 unlock
被调用。
在 Windows 7(64 位)下使用来自 MSYS2 的 Poco 1.9.0-1。
我有一个线程,发出三次 Poco:Condition 信号,休眠 300 毫秒。
我有两个线程使用两个不同的 类 EvListenerA 和 EvListenerB,它们从 Poco::Runnable 扩展而来,并且它们正在等待相同的 Poco::Condition 以显示带有 [=34= 的消息].
对于第一个和第二个信号,没有问题,但是当第三个信号启动时,只有线程 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] Receiving Event_2”?
EvListenerB 和 Event_2 发生了什么?
有什么想法吗?谢谢
嗯,对我来说这是未定义的行为。参考文献中明确指出 Condition
与 Mutex
或 FastMutex
一起使用。当wait
被调用时mutex
必须被锁定! - 您的代码中缺少它。
引用自reference:
A Condition object is always used in conjunction with a Mutex (or FastMutex) object.
和
Unlocks the mutex (which must be locked upon calling wait()) and waits for the given time until the Condition is signalled.
The given mutex will be locked again upon successfully leaving the function, even in case of an exception.
所以如果你想看到期望的输出,你必须调用 lock/unlock 到 mutex:
for (Poco::UInt32 i=0; i<3; i++)
{
mutex.lock(); // <--- lock mutex
condicion.wait(mutex);
cout << " [EvListenerA] Receiving Event_" << i << endl;
mutex.unlock(); // <--- unlock
}
对 EvListenerA
和 EvListenerB
类 进行相同的更改。
首先你要锁定互斥体。然后 wait
被调用,它解锁 mutex
并且我们等待直到 condition
发出信号,然后 wait
returns 并且互斥锁再次被锁定(在从 [ 返回之前=14=]).在离开 for 循环迭代的范围之前 unlock
被调用。