我对多线程没有多少经验,而且我正在编写一个我认为适合在两个线程中运行的c程序。程序将在串行端口上侦听数据,在可用时读取和处理新数据,并在请求时通过第三方IPC api(它令人困惑地命名为IPC)将最新处理的数据发布到其他(不相关的)模块。
为了接收通过IPC发布数据的请求,程序必须调用IPC_listenwait(wait_time);.然后,如果在“listenwaiting”时收到发布请求,则调用处理程序以发布最新数据。
一种选择是在一个线程中执行此操作,如:
for(;;) {
read_serial(inputBuffer);
process_data(inputBuffer, processedData); //Process and store
IPC_listenwait(wait_time); //If a request to publish is received during this,
} //then a handler will be invoked and the newest piece of
//processedData will be published to other modules
publishRequestHandler() { //Invoked when a message is received during IPC_listenwait
IPC_publish(newest(processedData));
}
这样可行,但对于应用程序来说,重要的是程序对发布新数据的请求非常敏感,并且发布的数据是最新的。这些目标不满足于上述目标,因为数据可能在过程开始监听等待之后并且在接收到发布消息请求之前到达。或者,当发布消息请求进入时,进程可能正在读取/处理,但在下一次IPC_listenwait调用之前无法为其提供服务。
我能想到的唯一一个设计是让一个线程可以读取,这样做会像:
readThread() {
for(;;) { //pseudocode
select();
read(inputBuffer);
process(inputBuffer, processedData);
}
}
让主线程只是监听传入消息:
mainThread() {
IPC_listenwait(forever);
}
publishRequestHandler() { //Invoked when a message is received during IPC_listenwait
IPC_publish(newest(processedData));
}
这是你要使用的设计吗?如果是这样,我在访问或编写processedData时是否需要使用信号量?
这会给我很好的回应吗?
由于
答案 0 :(得分:4)
你大部分时间都在正确的轨道上。
您必须注意的一件事是并发访问可发布的数据,因为您不希望一个线程破坏它而另一个线程试图读取它。为防止这种情况,请使用一对缓冲区和一个受互斥锁保护的指针,以指向被认为是当前的指针。当process_data()
准备就绪时,它应将其结果转储到非当前缓冲区,锁定指针互斥锁,将指针重新指向包含新数据的缓冲区,然后释放互斥锁。类似地,发布者应该在读取当前数据时锁定指针互斥锁,这将强制任何可能想要破坏它的东西等待。这比使用单个受互斥锁保护的缓冲区要复杂一些,但是可以确保在准备新数据时始终可以发布最新的内容。
如果您的处理步骤需要足够长的时间以便您可以读取多组数据,那么您可以将读取/处理线程分成两部分,让读者确保处理器只获得最新且最好的处理器,这样您就不会最终处理你不会发布的东西。
顺便说一下,第一个问题非常好。有一个upvote。