void wait(int timeInMs)
{
struct timespec timeToWait;
timeToWait.tv_sec = 5;
timeToWait.tv_nsec = timeInMs*1000;
int rt;
pthread_mutex_lock(&fakeMutex);
rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait);
pthread_mutex_unlock(&fakeMutex);
}
我正在使用此代码尝试让一个线程等待一下,但它根本不起作用。没有错误,它只是不会使程序执行得更慢。
我想也许每个线程都需要拥有它自己的条件和互斥量,但这对我来说真的没有意义。
答案 0 :(得分:16)
使用任何睡眠变体,都无法保证行为。由于内核不知道不同的线程,所有线程也可以休眠。
使用更安全,更清洁的解决方案是pthread_cond_timedwait
。您错误地使用了API。这是一个更好的例子:
pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;
void mywait(int timeInMs)
{
struct timespec timeToWait;
struct timeval now;
int rt;
gettimeofday(&now,NULL);
timeToWait.tv_sec = now.tv_sec+5;
timeToWait.tv_nsec = (now.tv_usec+1000UL*timeInMs)*1000UL;
pthread_mutex_lock(&fakeMutex);
rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait);
pthread_mutex_unlock(&fakeMutex);
printf("\nDone\n");
}
void* fun(void* arg)
{
printf("\nIn thread\n");
mywait(1000);
}
int main()
{
pthread_t thread;
void *ret;
pthread_create(&thread, NULL, fun, NULL);
pthread_join(thread,&ret);
}
您需要指定从当前时间等待的时间。因为你只告诉5秒和几纳秒,它发现时间已经过去而且没有等待...如果有任何疑问,请告诉我。
答案 1 :(得分:13)
pthread_cond_timedwait
函数需要绝对时间,而不是相对时间。您需要等待的时间,而不是等待的时间。
答案 2 :(得分:10)
pthread_cond_timedwait使用绝对时间,因此需要:
timeInMs是毫秒:1毫秒= 1000微秒= 1000 * 1000纳秒。
void wait(int timeInMs)
{
struct timeval tv;
struct timespec ts;
gettimeofday(&tv, NULL);
ts.tv_sec = time(NULL) + timeInMs / 1000;
ts.tv_nsec = tv.tv_usec * 1000 + 1000 * 1000 * (timeInMs % 1000);
ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
ts.tv_nsec %= (1000 * 1000 * 1000);
n = pthread_cond_timedwait(&condition, &mutex, &ts);
if (n == 0)
// TODO: singaled
else if (n == ETIMEDOUT)
// TODO: Time out.
}
答案 3 :(得分:3)
考虑到你正在使用timespec,你的目标不是同步而是等待我建议纳米睡眠。
#include <time.h>
.
.
.
struct timespec remain;
remain.tv_sec = 5;
remain.tv_nsec = timeInMs * 1000;
do {
if ( nanosleep( &remain, &remain ) == 0 || errno != EINTR ) {
break;
}
} while ( 1 );
.
.
.
答案 4 :(得分:2)
该代码无法休眠,它会检查条件一段时间。因为你可能没有设置cond ok它只是立即返回。
如果您不愿意在信号周围同步线程,那么pthread_cond _wait不是您需要的。检查here条件变量的工作原理。
如果你想用秒精确睡眠,请使用sleep
如果你想以微秒精度睡觉,请使用select时间长度。
答案 5 :(得分:1)
这是一个我从主循环创建线程的示例,它执行目录扫描并且超时为5秒。并且来自线程的信令使用全局的条件变量发生。我们一直在检查来自线程的信号:
pthread_cond_t C_KISU_SwagntUtilityBase::m_cond; /*Global variable*/
/*Inside main function*/
/*Local variables*/
pthread_condattr_t l_attr;
pthread_condattr_init(&l_attr);
pthread_condattr_setclock(&l_attr, CLOCK_MONOTONIC);
pthread_cond_init(&C_KISU_SwagntUtilityBase::m_cond, &l_attr);
Int32 l_threadid = pthread_create(&l_updatethread,NULL,C_KISU_SwagntUtilityBase::ThreadScanDirectoryByFilter,&l_filer);
if(CMP_ZERO == l_threadid)
{
pthread_mutex_t l_mutex = PTHREAD_MUTEX_INITIALIZER;
struct timespec l_ts;
if (clock_gettime(CLOCK_MONOTONIC, &l_ts) == INIT_NEGONE)
{
/* Handle error */
}
printf("\n Setting max time to run ThreadScanDirectoryByFilter as 5 second"));
l_ts.tv_sec += l_filer.m_max_scan_time;
if(l_filer.m_scan_status == 0)
{
pthread_mutex_lock(&l_mutex);
int l_rt = pthread_cond_timedwait(&C_KISU_SwagntUtilityBase::m_cond, &l_mutex, &l_ts);
if (ETIMEDOUT == l_rt)
{
printf("\n timeout has happened before scan routine could finish"));
}
else if (EOK == l_rt)
{
printf("\n Scan successful"));
}
else
{
printf("\n Unknown error while timeout condition check"));
}
pthread_mutex_unlock(&l_mutex);
}
}
else
{
printf("\n Error while creating thread\n");
}
答案 6 :(得分:0)
主要参考:http://pubs.opengroup.org/onlinepubs/009695299/functions/pthread_cond_timedwait.html
上面andrewrk的代码的修正
我可以确认Adrian May的gettimeofday不能正常运行! 像这样的无限线程内的andrewrk的代码行为
static void * thread_infinite(void * unused) {
while (1) {
// compute stuff
mywait(5);
}
是不可预测的:它运行大约700倍,直到阻塞!
andrewrk的正确代码版本是:
pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;
void mywait(int timeInS)
{
struct timespec ts;
struct timeval now;
int rt = 0;
// gettimeofday(&now,NULL); // DOES NOT FUNCTION CORRECTLY
// timeToWait.tv_sec = now.tv_sec+5;
// timeToWait.tv_nsec = (now.tv_usec+1000UL*timeInMs)*1000UL;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += timeInS;
pthread_mutex_lock(&fakeMutex);
do {
rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &ts);
}
while (rt == 0);
pthread_mutex_unlock(&fakeMutex);
}