我想要创建一个线程,它等待由两个定时器在过期时发出信号的事件。当线程接收到信号时,它必须进行一些图像处理。我从下面的代码开始。(这是线程显示消息而不是进行图像处理的非常基本的实现)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/signal.h>
#include <sys/time.h>
struct itimerspec ts1,ts2;
struct sigevent se1,se2;
timer_t timerId1,timerId2;
pthread_cond_t imageProcessCond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t imageProcessMutex = PTHREAD_MUTEX_INITIALIZER;
void* imageProcessThread()
{
int status = 0;
int i = 0;
while(i<2){
status = pthread_mutex_lock (&imageProcessMutex);
if(status != 0){
perror("pthread_mutex_lock\n");
exit(status);
}
status = pthread_cond_wait (&imageProcessCond, &imageProcessMutex);
if (status != 0){
perror("pthread_cond_wait\n");
exit(status);
}
printf("signal received %s\n",__TIME__);
i++;
status = pthread_mutex_unlock (&imageProcessMutex);
if(status != 0){
perror("pthread_mutex_unlock\n");
exit(status);
}
}
}
void timerFunc1 ()
{
int status = 0;
status = pthread_mutex_lock (&imageProcessMutex);
if (status != 0){
perror("pthread_mutex_lock\n");
exit(EXIT_FAILURE);
}
printf("timer1 took lock %s\n",__TIME__);
status = pthread_cond_signal (&imageProcessCond);
if (status != 0){
perror("pthread_cond_signal\n");
exit(EXIT_FAILURE);
}
printf("timer1 signalled %s\n",__TIME__);
status = pthread_mutex_unlock (&imageProcessMutex);
if (status != 0){
perror("pthread_mutex_unlock\n");
exit(status);
}
printf("timer1 released lock %s\n",__TIME__);
}
void timerFunc2 ()
{
int status = 0;
status = pthread_mutex_lock (&imageProcessMutex);
if (status != 0){
perror("pthread_mutex_lock\n");
exit(EXIT_FAILURE);
}
printf("timer2 took lock %s\n",__TIME__);
status = pthread_cond_signal (&imageProcessCond);
if (status != 0){
perror("pthread_cond_signal\n");
exit(EXIT_FAILURE);
}
printf("timer2 signalled %s\n",__TIME__);
status = pthread_mutex_unlock (&imageProcessMutex);
if (status != 0){
perror("pthread_mutex_unlock\n");
exit(status);
}
printf("timer2 released lock %s\n",__TIME__);
}
int main()
{
int status = 0;
pthread_t tImageProcessId;
se1.sigev_notify = SIGEV_THREAD;
se1.sigev_value.sival_ptr = &timerId1;
se1.sigev_notify_function = timerFunc1;
se1.sigev_notify_attributes = NULL;
ts1.it_value.tv_sec = 20;
ts1.it_value.tv_nsec = 0;
ts1.it_interval.tv_sec = 20;
ts1.it_interval.tv_nsec = 0;
se2.sigev_notify = SIGEV_THREAD;
se2.sigev_value.sival_ptr = &timerId2;
se2.sigev_notify_function = timerFunc2;
se2.sigev_notify_attributes = NULL;
ts2.it_value.tv_sec = 20;
ts2.it_value.tv_nsec = 0;
ts2.it_interval.tv_sec = 20;
ts2.it_interval.tv_nsec = 0;
status = pthread_create((&tImageProcessId), NULL, &imageProcessThread, NULL);
if(status!= 0){
perror("pthread_create\n");
exit(EXIT_FAILURE);
}
status = timer_create(CLOCK_REALTIME, &se1, &timerId1);
if (status != 0){
perror("timer_create\n");
exit(EXIT_FAILURE);
}
status = timer_create(CLOCK_REALTIME, &se2, &timerId2);
if (status != 0){
perror("timer_create\n");
exit(EXIT_FAILURE);
}
status = timer_settime(timerId1, 0, &ts1, 0);
if (status != 0){
perror("timer_create\n");
exit(EXIT_FAILURE);
}
status = timer_settime(timerId2, 0, &ts2, 0);
if (status != 0){
perror("timer_create\n");
exit(EXIT_FAILURE);
}
sleep(80);
}我已经为相同的时间间隔配置了两个定时器(我只是为了测试目的模拟了这个条件),在实际场景中,定时器将被配置为不同的时间间隔,但在这种情况下,它们可能同时到期)。
我的理解是:
但是当我运行上面的代码时,线程实际上缺少了由timer1发出信号的事件。
这是我得到的输出
timer1锁11:40:20
timer1信号: 11:40:20
timer2锁11:40:20
timer2信号: 11:40:20
收到信号11:40:20
timer2释放锁11:40:20
timer1释放锁11:40:20
由timer1发出信号的事件正在消失。一旦timer1释放锁,计时器2就会获得锁,并且线程不会被执行。
如何确保控件从timer1到线程再到timer2?还有其他方法来实现这一点吗?请帮我解决这个问题
提前感谢
你好,阿皮塔
发布于 2014-01-08 13:15:49
imageProcessThread函数存在同步中断。从imageProcessMutex互斥锁到下一个锁(第二个“同时”迭代),代码不同步。可能第二个通知是从TimerFunc2函数发送的,当imageProcessThread不等待imageProcessCond时,这个通知就不会发生了。另一件重要的事情是虚假的唤醒。即使pthread_cond_wait函数没有发送通知,TimerFunc也可能会醒来。在您的情况下(根据输出),它不会发生,但可能发生在其他条件下,应该得到适当的处理:当通知(真实的或虚假的)到达pthread_cond_wait时,再次检查谓词。
您的代码可以稍加修改以修复上面的漏洞。其主要思想是在函数之间共享局部变量i,让计时器增量它,并完全保护“main”等待循环。
struct itimerspec ts1,ts2;
struct sigevent se1,se2;
timer_t timerId1,timerId2;
pthread_cond_t imageProcessCond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t imageProcessMutex = PTHREAD_MUTEX_INITIALIZER;
int i = 0;
void* imageProcessThread()
{
int status = 0;
//int i = 0;
status = pthread_mutex_lock (&imageProcessMutex);
while(i<2){
//status = pthread_mutex_lock (&imageProcessMutex);
status = pthread_cond_wait (&imageProcessCond, &imageProcessMutex);
printf("signal received %s\n",__TIME__);
//i++;
//status = pthread_mutex_unlock (&imageProcessMutex);
}
status = pthread_mutex_unlock (&imageProcessMutex);
}
void timerFunc1 ()
{
int status = 0;
status = pthread_mutex_lock (&imageProcessMutex);
i++;
printf("timer1 took lock %s\n",__TIME__);
status = pthread_cond_signal (&imageProcessCond);
printf("timer1 signalled %s\n",__TIME__);
status = pthread_mutex_unlock (&imageProcessMutex);
printf("timer1 released lock %s\n",__TIME__);
}
void timerFunc2 ()
{
int status = 0;
status = pthread_mutex_lock (&imageProcessMutex);
i++;
printf("timer2 took lock %s\n",__TIME__);
status = pthread_cond_signal (&imageProcessCond);
printf("timer2 signalled %s\n",__TIME__);
status = pthread_mutex_unlock (&imageProcessMutex);
printf("timer2 released lock %s\n",__TIME__);
}
int main()
{
int status = 0;
pthread_t tImageProcessId;
se1.sigev_notify = SIGEV_THREAD;
se1.sigev_value.sival_ptr = &timerId1;
se1.sigev_notify_function = timerFunc1;
se1.sigev_notify_attributes = NULL;
ts1.it_value.tv_sec = 20;
ts1.it_value.tv_nsec = 0;
ts1.it_interval.tv_sec = 20;
ts1.it_interval.tv_nsec = 0;
se2.sigev_notify = SIGEV_THREAD;
se2.sigev_value.sival_ptr = &timerId2;
se2.sigev_notify_function = timerFunc2;
se2.sigev_notify_attributes = NULL;
ts2.it_value.tv_sec = 20;
ts2.it_value.tv_nsec = 0;
ts2.it_interval.tv_sec = 20;
ts2.it_interval.tv_nsec = 0;
status = pthread_create((&tImageProcessId), NULL, &imageProcessThread, NULL);
status = timer_create(CLOCK_REALTIME, &se1, &timerId1);
status = timer_create(CLOCK_REALTIME, &se2, &timerId2);
status = timer_settime(timerId1, 0, &ts1, 0);
status = timer_settime(timerId2, 0, &ts2, 0);
sleep(80);
}另一个次要通知是关于
__TIME__这是一个编译时间,因此您的输出将在每一行中显示相同的时间值。
我还建议阅读有关障碍同步的内容。
发布于 2014-01-09 09:18:15
谢谢你的答复
即使有上面的代码,我也错过了一个事件。我需要一个接一个地接收这些事件。
如果在锁定imageProcessMutex之前再使用一个锁,那么它工作正常。这两个事件都由图像处理线程接收。请看下面的代码。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/signal.h>
#include <sys/time.h>
struct itimerspec ts1,ts2;
struct sigevent se1,se2;
timer_t timerId1,timerId2;
pthread_cond_t imageProcessCond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t imageProcessMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mainMutex = PTHREAD_MUTEX_INITIALIZER;
void* imageProcessThread()
{
int status = 0;
int i =0;
status = pthread_mutex_lock (&imageProcessMutex);
while(i<2){
status = pthread_cond_wait (&imageProcessCond, &imageProcessMutex);
printf("signal received %s\n",__TIME__);
i++;
}
status = pthread_mutex_unlock (&imageProcessMutex);
}
void timerFunc1 ()
{
int status = 0;
status = pthread_mutex_lock (&mainMutex);
status = pthread_mutex_lock (&imageProcessMutex);
printf("timer1 took image process lock %s\n",__TIME__);
status = pthread_cond_signal (&imageProcessCond);
printf("timer1 signalled %s\n",__TIME__);
status = pthread_mutex_unlock (&imageProcessMutex);
printf("timer1 released image process lock %s\n",__TIME__);
status = pthread_mutex_unlock (&mainMutex);
}
void timerFunc2 ()
{
int status = 0;
status = pthread_mutex_lock (&mainMutex);
status = pthread_mutex_lock (&imageProcessMutex);
printf("timer2 took image process lock %s\n",__TIME__);
status = pthread_cond_signal (&imageProcessCond);
printf("timer2 signalled %s\n",__TIME__);
status = pthread_mutex_unlock (&imageProcessMutex);
printf("timer2 released image lock %s\n",__TIME__);
status = pthread_mutex_unlock (&mainMutex);
}
int main()
{
int status = 0;
pthread_t tImageProcessId;
se1.sigev_notify = SIGEV_THREAD;
se1.sigev_value.sival_ptr = &timerId1;
se1.sigev_notify_function = timerFunc1;
se1.sigev_notify_attributes = NULL;
ts1.it_value.tv_sec = 20;
ts1.it_value.tv_nsec = 0;
ts1.it_interval.tv_sec = 0;
ts1.it_interval.tv_nsec = 0;
se2.sigev_notify = SIGEV_THREAD;
se2.sigev_value.sival_ptr = &timerId2;
se2.sigev_notify_function = timerFunc2;
se2.sigev_notify_attributes = NULL;
ts2.it_value.tv_sec = 20;
ts2.it_value.tv_nsec = 0;
ts2.it_interval.tv_sec = 0;
ts2.it_interval.tv_nsec = 0;
status = pthread_create((&tImageProcessId), NULL, &imageProcessThread, NULL);
status = timer_create(CLOCK_REALTIME, &se1, &timerId1);
status = timer_create(CLOCK_REALTIME, &se2, &timerId2);
status = timer_settime(timerId1, 0, &ts1, 0);
status = timer_settime(timerId2, 0, &ts2, 0);
sleep(80);
}我得到了以下输出
timer1拍摄了图像处理锁14:14:28
timer1信号14:14:28
收到信号14:14:28
timer1发布图像处理锁14:14:28
timer2拍摄了图像处理锁14:14:28
timer2信号14:14:28
timer2发布图像锁14:14:28
收到信号14:14:28
有了这个,我就不会错过任何一个事件。
我只想知道这是否可以在不使用pthread_cond_wait和pthread_cond_signal的情况下实现。
此外,您所提到的Barrier同步主要用于在多个线程(2个或多个线程)之间实现同步。但是在我的例子中,只有一个线程在等待event.So,我不确定障碍同步是否是正确的方法。请参考链接。
http://geekswithblogs.net/jolson/archive/2009/02/09/an-intro-to-barrier.aspx
感谢并致以问候
阿皮塔
https://stackoverflow.com/questions/20991097
复制相似问题