您的位置:首页 > 大数据 > 人工智能

研究条件变量pthread_cond_wait的机制

2018-03-31 10:45 344 查看

1条件变量的解释:

  条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。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()则激活所有等待线程。
 
 

2对pthread_cond_wait测试

2.1方法:

    在某多线程文件转发协议的代码里加上日志和睡眠时间进行测试。配置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);
......
}
 

2.2测试日志

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]]
 

2.3分析

       pthread_cond_wait内部自带解锁和加锁,在InitTcpThread创建链路检测的线程和锁函数调用它之前必须求本线程加锁(pthread_mutex_lock(&gInitLock)),刚进入pthread_cond_wait时gInitCount =0,随后pthread_cond_wait解锁&gInitLock并等待条件满足。之后,tcpChkLinkTaskProc HTTP SA工作线程的五个线程以此起来(对gInitLock加锁,gInitCount自增,pthread_cond_signal(&gInitCond)发信号给等待线程,对gInitLock解锁),第五个信号发出后InitTcpThread链路检测的线程里的“gInitCount < TCP_THREAD_NUM”便不再成立,链路检测线程的代码继续往下走。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息