小心pthread cond signal和SetEvent之间的差异

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

小心pthread_cond_signalSetEvent之间的差异

 

转载时请注明出处和作者联系方式:http://blog.csdn.net/absurd

作者联系方式:Li XianJing <xianjimli at hotmail dot com>

更新时间:2006-12-19

 

今天帮同事查一个多线程的BUG,其中一个线程挂在g_cond_wait上不动了。从代码来看,看出不出任何问题,g_cond_waitg_cond_signal是严格配对的。折腾了两个小时后,从LOG信息中发现,g_cond_waitg_cond_signal的顺序有点问题,一个线程先调g_cond_signal,另外一个线程才调g_cond_wait

 

g_cond_signalglib的封装,在Linux下,是用pthread_cond_signal模拟的,在Win32下,是用SetEvent模拟的。在Win32下,SetEventWaitForSingleObject在两个线程中的调用顺序没有关系,奇怪,难道在linux下两者的调用顺序有影响吗?

 

看了pthread的代码,果然如此:pthread_cond_signal发现没有其它线程等待,它直接返回了(见用红色高亮的代码)

       
           

int pthread_cond_signal(pthread_cond_t *cond)

           

{

           

    if (cond == NULL)

           

        return pth_error(EINVAL, EINVAL);

           

    if (*cond == PTHREAD_COND_INITIALIZER)

           

        if (pthread_cond_init(cond, NULL) != OK)

           

            return errno;

           

    if (!pth_cond_notify((pth_cond_t *)(*cond), FALSE))

           

        return errno;

           

    return OK;

           

}

           

int pth_cond_notify(pth_cond_t *cond, int broadcast)

           

{      

           

    /* consistency checks */

           

    if (cond == NULL)

           

        return pth_error(FALSE, EINVAL);

           

    if (!(cond->cn_state & PTH_COND_INITIALIZED))

           

        return pth_error(FALSE, EDEADLK);

           

   

           

    /* do something only if there is at least one waiters (POSIX semantics) */

           

    if (cond->cn_waiters > 0) {

           

        /* signal the condition */

           

        cond->cn_state |= PTH_COND_SIGNALED;

           

        if (broadcast)

           

            cond->cn_state |= PTH_COND_BROADCAST;

           

        else

           

            cond->cn_state &= ~(PTH_COND_BROADCAST);

           

        cond->cn_state &= ~(PTH_COND_HANDLED);

           

   

           

        /* and give other threads a chance to awake */

           

        pth_yield(NULL);

           

    }

           

 

           

    /* return to caller */

           

    return TRUE;

           

}

           

 

晚上回家后,我又看了reactos关于SetEvent的实现。结果也意料之中:没有线程等待这个Event时,它仍然会设置SignalState(见用红色高亮的代码)

           

LONG

           

STDCALL

           

KeSetEvent(PKEVENT Event,

           

           KPRIORITY Increment,

           

           BOOLEAN Wait)

           

{

           

    KIRQL OldIrql;

           

    LONG PreviousState;

           

    PKWAIT_BLOCK WaitBlock;

           

 

           

    DPRINT("KeSetEvent(Event %x, Wait %x)/n",Event,Wait);

           

 

           

    /* Lock the Dispathcer Database */

           

    OldIrql = KeAcquireDispatcherDatabaseLock();

           

 

           

    /* Save the Previous State */

           

    PreviousState = Event->Header.SignalState;

           

 

           

    /* Check if we have stuff in the Wait Queue */

           

    if (IsListEmpty(&Event->Header.WaitListHead)) {

           

 

           

        /* Set the Event to Signaled */

           

        DPRINT("Empty Wait Queue, Signal the Event/n");

           

        Event->Header.SignalState = 1;

           

    } else {

           

 

           

        /* Get the Wait Block */

           

        WaitBlock = CONTAINING_RECORD(Event->Header.WaitListHead.Flink,

           

                                      KWAIT_BLOCK,

           

                                      WaitListEntry);

           

 

           

 

           

        /* Check the type of event */

           

        if (Event->Header.Type == NotificationEvent || WaitBlock->WaitType == WaitAll) {

           

 

           

            if (PreviousState == 0) {

           

 

           

                /* We must do a full wait satisfaction */

           

                DPRINT("Notification Event or WaitAll, Wait on the Event and Signal/n");

           

                Event->Header.SignalState = 1;

           

                KiWaitTest(&Event->Header, Increment);

           

            }

           

 

           

        } else {

           

 

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
这里写图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值