一尘不染

pThread同步问题

linux

我面临pthread的同步问题。threadWaitFunction1,是线程等待函数。我希望行号。flag = 1仅在243-246完成后才执行247
。但我感到奇怪的是,有时它会在243-246完成之前直接跳到247。

请帮我。

提前致谢。

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从代码中删除。 * 编辑:更改了互斥锁内的标志(仍然不起作用) *


阅读 253

收藏
2020-06-07

共1个答案

一尘不染

因此,真正使执行不满意的不是真正的执行顺序(这很可能是正确的)。在“它在243-246完成之前直接跳到247”下的意思是“我观察到它在应在244中等待的时间过去之前执行了247”。对?

然后,我怀疑这是虚假唤醒的问题:即使没有其他线程发出条件变量的信号,一个线程也可能被唤醒。的规范pthread_cond_timedwait()说:“可能会发生从pthread_cond_timedwait()或pthread_cond_wait()函数的虚假唤醒。”

通常,条件变量与应用程序中的某个事件相关联,实际上,等待条件变量的线程会等待另一个线程发出的信号,表明相关事件已经发生。如果您没有事件,只是想等待一定的时间,那么实际上其他方法(例如usleep()timers)更合适,除非您还需要pthread取消点。

补充:由于您似乎很满意,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


ADDED-3:现在,在您更改问题中的代码以通过超时而不增加当前时间后,它又出现了另一个问题。如规范所述,超时pthread_cond_timedwait()是绝对时间,不是相对时间;因此,如果您将超时时间设置为3秒,则将其解释为“自系统时间参考点起3秒”。几乎可以肯定,这一刻已经过去了一段时间,因此pthread_cond_timedwait()立即返回。
我建议您通读规范(包括基本原理),以更好地了解应该如何使用此功能。

2020-06-07