Vuz*_*uzi 5 c++ multithreading signals c++11
我在使用线程和信号设计应用程序的主要工作流时遇到了一些困难。
我的目标是要有一个主线程,捕获信号以及n个其他线程定期执行操作(实际上是在树莓派上使用传感器,并保存检索到的数据)。我希望能够以一种干净的方式关闭程序,即在关闭传感器之前等待传感器完成数据写入(如果它们是在发生信号时)。我正在使用C ++ 11。
现在,我有这个例子:
#include <iostream>
#include <thread>
#include <csignal>
#include <mutex>
#define NUM_THREAD 3;
static volatile int stop = 0; // If the threads needs to stop
std::mutex m; // Mutex
void threadHandle(int tid) {
while(1) {
std::cout << "Launched by thread " << tid << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "I have sleep well " << tid << std::endl;
m.lock();
if(stop) {
std::cout << "Thread " << tid << " needs to stop" << std::endl;
m.unlock();
break;
}
m.unlock();
}
}
void signalHandler(int signum) {
m.lock();
std::cout << "Signal " << signum << " received" << std::endl;
stop = 1;
m.unlock();
}
int main() {
std::thread t[NUM_THREAD];
std::signal(SIGINT, signalHandler);
//Launch a group of threads
for (int i = 0; i < NUM_THREAD; i++) {
t[i] = std::thread(call_from_thread, i);
}
std::cout << "Launched from the main\n";
for (int i = 0; i < NUM_THREAD; i++) {
t[i].join();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的止损值是可变的,仅因为我在信号处理程序中使用了它。我应该使用std :: atomic_int来确保原子调用信号值吗?互斥量真的有必要吗?或更笼统地说,这是实现我想要的一个好方法吗?
我可能遇到的另一个问题是,某些传感器在两次测量之间的等待时间可能会很长(例如2或3个小时),因此我需要每2或3秒检查一次停止值..感觉真的很干净。另一种解决方案是向线程发送信号,使我可以简单地使线程“休眠”。但是同样,我没有控件可以告诉线程在终止之前完成其操作。
提前致谢 !
信号处理程序中不允许对互斥体进行操作。您可以将stop变量分成两个:
stop_main,在信号处理程序中设置,并在主线程中等待。因为信号处理程序是在主线程的上下文中执行的,所以将其声明为volatile(或std::atomic)就足够了。stop_threads,它在主线程中设置,并被其他线程等待。此变量最合适的类型是std::condition_variable。这种类型也有助于您长时间的等待。像这样的东西:
std::atomic<int> stop_main = 0;
std::condition_variable stop_threads;
std::mutex m; // protects 'stop_threads'
void threadHandle(int tid)
{
while(1)
{
/* .. do something .. */
std::unique_lock<std::mutex> l(m);
if(stop_threads.wait_for(l, std::chrono::hours(2)) ==
std::cv_status::no_timeout) break;
}
}
void signalHandler(int signum)
{
stop_main.store(1);
}
int main()
{
std::thread t[NUM_THREAD];
std::signal(SIGINT, signalHandler);
for (int i = 0; i < NUM_THREAD; i++) {
t[i] = std::thread(threadHandle, i);
while(!stop_main.load())
{
/* Some workload may be here */
sleep(10); // Signals will interrupt this function.
}
stop_threads.notify_all();
for (int i = 0; i < NUM_THREAD; i++) {
t[i].join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我不确定 c++ 是否保证信号传递到主线程,而不是其他线程。否则你需要阻塞其他线程中的信号。
sleep(10)主线程中的内容可以替换为任何可被信号中断的函数。