我面临pthread的同步问题。threadWaitFunction1,是线程等待函数。我希望行号。flag = 1仅在243-246完成后才执行247 。但我感到奇怪的是,有时它会在243-246完成之前直接跳到247。
flag = 1
请帮我。
提前致谢。
236 struct timespec timeToWait; 237 static void* threadWaitFunction1(void *timeToWaitPtr) 238 { 239 cout << "Setting flag =0 inside threadWaitFunction1\n"; 240 241 cout << "Inside threadWaitFunction\n"; 242 struct timespec *ptr = (struct timespec*) timeToWaitPtr; 243 pthread_mutex_lock(&timerMutex); flag = 0; 244 pthread_cond_timedwait(&timerCond, &timerMutex, ptr); flag=1; 245 pthread_mutex_unlock(&timerMutex); 246 cout << "Setting flag =1 inside threadWaitFunction1\n"; 247 248 249 }
创建并调用上述线程的线程是:
263 static void timer_trackStartTime () 264 { 265 struct timeval now; 266 pthread_t thread; 267 268 printf("Inside trackStartTime: flag = %d\n",flag); 269 270 /* Setting timer expiration */ 271 timeToWait.tv_sec = lt_leak_start_sec;; // First expiry after 1 sec 272 timeToWait.tv_nsec = lt_leak_start_nsec; 273 pthread_create(&thread, NULL, threadWaitFunction1, &timeToWait); 274 pthread_join(thread, NULL); 275 //pthread_kill(thread, SIGKILL); // Destroying the thread to ensure no leaks 276 . . 283 }
如果我使用pthread_mutex_lock保护整个函数,但仍然存在相同的问题。 如何确保有序执行?有人可以帮忙吗?
编辑:now.tv_sec和now.tv_nsec从代码中删除。 * 编辑:更改了互斥锁内的标志(仍然不起作用) *
因此,真正使执行不满意的不是真正的执行顺序(这很可能是正确的)。在“它在243-246完成之前直接跳到247”下的意思是“我观察到它在应在244中等待的时间过去之前执行了247”。对?
然后,我怀疑这是虚假唤醒的问题:即使没有其他线程发出条件变量的信号,一个线程也可能被唤醒。的规范pthread_cond_timedwait()说:“可能会发生从pthread_cond_timedwait()或pthread_cond_wait()函数的虚假唤醒。”
pthread_cond_timedwait()
通常,条件变量与应用程序中的某个事件相关联,实际上,等待条件变量的线程会等待另一个线程发出的信号,表明相关事件已经发生。如果您没有事件,只是想等待一定的时间,那么实际上其他方法(例如usleep()或timers)更合适,除非您还需要pthread取消点。
usleep()
补充:由于您似乎很满意,usleep()并且仅询问为什么pthread_cond_timedwait()不符合您的期望,所以我决定不发布代码。如果需要,可以使用@Hasturkun的答案。
ADDED-2:以下注释中的输出(在应用Hasturkun解决方案之后获得)表明等待线程没有退出循环,这可能意味着pthread_cond_timedwait()返回的内容与ETIMEDOUT不同。您是否看到过@nos对您的帖子的评论(我固定了要减去的纳秒数):
确保(now.tv_usec * 1000)+ lt_leak_start_nsec; 不会溢出。您只能将tv_nsec设置为最大999999999,如果表达式大于该值,则应从tv_nsec减去1000000000,然后将tv_sec递增1。如果您的timeToWaitPtr包含无效的tv_nsec(大于999999999),则pthread_cond_timedwait将失败(您应检查其返回值也是如此。)–否Apr 4月28日19:04
在这种情况下,pthread_cond_timedwait()将反复返回EINVAL并且永远不会退出循环。最好在进入等待循环之前调整超时,尽管也可以响应来完成EINVAL。
EINVAL
ADDED-3:现在,在您更改问题中的代码以通过超时而不增加当前时间后,它又出现了另一个问题。如规范中所述,超时pthread_cond_timedwait()是绝对时间,不是相对时间;因此,如果您将超时时间设置为3秒,则将其解释为“自系统时间参考点起3秒”。几乎可以肯定,这一刻已经过去了一段时间,因此pthread_cond_timedwait()立即返回。 我建议您通读规范(包括基本原理),以更好地了解应该如何使用此功能。