条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
等待条件有两种方式:条件等待pthread_cond_wait()和计时等待pthread_cond_timedwait(),其中计时等待方式如果在给定时刻前条件没有满足,则返回ETIMEDOUT,结束等待,其中abstime以与time()条件变量相同意义的绝对时间形式出现,表示格林尼治时间1970年1月1日0时0分0秒。
无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait()(或pthread_cond_timedwait(),下同)的竞争条件(Race Condition)。mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。阻塞时处于解锁状态。
激发条件有两种形式,pthread_cond_signal()激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个;而pthread_cond_broadcast()则激活所有等待线程。
在某多线程文件转发协议的代码里加上日志和睡眠时间进行测试。配置TCP_THREAD_NUM=5 。
* 函数名称:InitTcpThread
* 功能描述:创建链路检测的线程和锁
BOOLEAN InitTcpThread()
{
......
LOG("TEST1 InitTcpThread gInitCount:%d,TCP_THREAD_NUM:%d.",gInitCount,TCP_THREAD_NUM);
//等待处理线程池ready ok,只能在一个线程中等待
pthread_mutex_lock(&gInitLock);
while (gInitCount < TCP_THREAD_NUM)
{
LOG("TEST2 InitTcpThread gInitCount:%d,TCP_THREAD_NUM:%d.",gInitCount,TCP_THREAD_NUM);
pthread_cond_wait(&gInitCond, &gInitLock);
LOG("TEST3 InitTcpThread gInitCount:%d,TCP_THREAD_NUM:%d.",gInitCount,TCP_THREAD_NUM);
}
pthread_mutex_unlock(&gInitLock);
LOG("TEST4 InitTcpThread gInitCount:%d,TCP_THREAD_NUM:%d.",gInitCount,TCP_THREAD_NUM);
......
}
......
}
* 函数名称:tcpChkLinkTaskProc
* 功能描述:HTTP SA工作线程
VOID tcpChkLinkTaskProc(LPVOID lpPno)
{
......
sleep(1);
LOG(" TEST1 tcpChkLinkTaskProc gInitCount:%d. ",gInitCount);
//条件变量,通知listening thread
pthread_mutex_lock(&gInitLock);
LOG(" TEST2 tcpChkLinkTaskProc gInitCount:%d. ",gInitCount);
sleep(1);
gInitCount++;
LOG(" TEST3 tcpChkLinkTaskProc gInitCount:%d. ",gInitCount);
pthread_cond_signal(&gInitCond);
LOG(" TEST4 tcpChkLinkTaskProc gInitCount:%d. ",gInitCount);
pthread_mutex_unlock(&gInitLock);
LOG(" TEST5 tcpChkLinkTaskProc gInitCount:%d. ",gInitCount);
......
}
18-03-29 12:51:52:189 [TEST1 InitTcpThread gInitCount:0,TCP_THREAD_NUM:5.]
18-03-29 12:51:52:189 [TEST2 InitTcpThread gInitCount:0,TCP_THREAD_NUM:5.]
18-03-29 12:51:53:189 [ TEST1 tcpChkLinkTaskProc gInitCount:0. ]
18-03-29 12:51:53:189 [ TEST1 tcpChkLinkTaskProc gInitCount:0. ]
18-03-29 12:51:53:189 [ TEST1 tcpChkLinkTaskProc gInitCount:0. ]
18-03-29 12:51:53:189 [ TEST1 tcpChkLinkTaskProc gInitCount:0. ]
18-03-29 12:51:53:189 [ TEST2 tcpChkLinkTaskProc gInitCount:0. ]
18-03-29 12:51:53:190 [ TEST1 tcpChkLinkTaskProc gInitCount:0. ]
18-03-29 12:51:54:190 [ TEST3 tcpChkLinkTaskProc gInitCount:1. ]
18-03-29 12:51:54:190 [ TEST4 tcpChkLinkTaskProc gInitCount:1. ]
18-03-29 12:51:54:190 [ TEST5 tcpChkLinkTaskProc gInitCount:1. ]
18-03-29 12:51:54:190 [ TEST2 tcpChkLinkTaskProc gInitCount:1. ]
18-03-29 12:51:55:190 [ TEST3 tcpChkLinkTaskProc gInitCount:2. ]
18-03-29 12:51:55:190 [ TEST4 tcpChkLinkTaskProc gInitCount:2. ]
18-03-29 12:51:55:190 [ TEST5 tcpChkLinkTaskProc gInitCount:2. ]
18-03-29 12:51:55:190 [ TEST2 tcpChkLinkTaskProc gInitCount:2. ]
18-03-29 12:51:56:191 [ TEST3 tcpChkLinkTaskProc gInitCount:3. ]
18-03-29 12:51:56:191 [ TEST4 tcpChkLinkTaskProc gInitCount:3. ]
18-03-29 12:51:56:191 [ TEST5 tcpChkLinkTaskProc gInitCount:3. ]
18-03-29 12:51:56:191 [ TEST2 tcpChkLinkTaskProc gInitCount:3. ]
18-03-29 12:51:57:191 [ TEST3 tcpChkLinkTaskProc gInitCount:4. ]
18-03-29 12:51:57:191 [ TEST4 tcpChkLinkTaskProc gInitCount:4. ]
18-03-29 12:51:57:191 [ TEST5 tcpChkLinkTaskProc gInitCount:4. ]
18-03-29 12:51:57:191 [ TEST2 tcpChkLinkTaskProc gInitCount:4. ]
18-03-29 12:51:58:191 [ TEST3 tcpChkLinkTaskProc gInitCount:5. ]
18-03-29 12:51:58:191 [ TEST4 tcpChkLinkTaskProc gInitCount:5. ]
18-03-29 12:51:58:191 [ TEST5 tcpChkLinkTaskProc gInitCount:5. ]
18-03-29 12:51:58:191 [TEST3 InitTcpThread gInitCount:5,TCP_THREAD_NUM:5.]
18-03-29 12:51:58:192 [TEST4 InitTcpThread gInitCount:5,TCP_THREAD_NUM:5.]
18-03-29 12:51:58: [InitTcpThread--Index[0]:host[10.46.181.23] port[5881]]
18-03-29 12:51:58: [InitTcpThread--ListenThreadNum[1] WorkThreadNum[5]]