首页 文章

定时开销二进制信号量与互斥量

提问于
浏览
3

我在vxWorks平台上运行了一个示例C程序来测试互斥量和二进制信号量之间的时序差异 . 以下程序是原型

SEM ID semMutex;
UINT ITER = 10000;
taskIdOne = TASKSPAWN("t1",TASK_PRIORITY_2,0,8192,0,(FUNCPTR)myMutexMethod,0,0);
taskIdTwo = TASKSPAWN("t2",TASK_PRIORITY_2,0,8192,0,(FUNCPTR)myMutexMethod,0,0);
void myMutexMethod(void)
    {
        int i;
        VKI_PRINTF("I'm  (%s)\n",TASKNAME(0) );
        myMutexTimer.start();
        for (i=0; i < ITER; i++)
        {
            MUTEX_LOCK(semMutex,WAIT_FOREVER); 
            ++global;                     
            MUTEX_UNLOCK(semMutex); 
        } 
        myMutexTimer.stop();
        myMutexTimer.show();
    }

在上面的程序中存在争用(2个任务正在尝试获取互斥锁) . 我的计时器为上述程序打印了37.43毫秒 . 使用相同的原型,二进制信号量程序只用了2.8毫秒 . 这是可以理解的,因为二进制信号量是轻量级的,并且没有许多功能,如互斥锁(优先级倒置,所有权等) .

但是,我删除了一个任务并运行了上述程序(没有争用) . 由于没有争用,任务t1只获取互斥锁,执行临界区,然后释放互斥锁 . 与二进制信号量相同 .
对于时间,互斥量我得到3.35毫秒和二进制信号量4毫秒 .

当没有争用时,我很惊讶地看到互斥锁比二进制信号量更快 .
这是预期的吗?还是我错过了什么?

任何帮助表示赞赏 . !

1 回答

  • 1

    在这种情况下,互斥体可能更快,因为相同的任务一次又一次地重复使用,而不涉及其他任务 . 我的猜测是互斥代码采用了一种快捷方式来启用递归互斥调用(即同一个任务需要两次相同的互斥锁) . 即使您的代码在技术上不是递归互斥,但代码可能使用相同的快捷方式,因为信号量所有者未被任何其他获取信号量的任务覆盖 .

    换句话说,你这样做:

    1) semTake(semMutex)
    2) ++global;
    3) semGive(semMutex) // sem owner flag is not changed
    4) sameTake(semMutex) // from same task as previous semTake
    ...
    

    然后在步骤4中,semTake看到sem owner ==当前任务id(因为sem所有者在步骤1中设置并且从未更改为其他任何内容),因此它只是将信号量标记为已采用并快速跳出 .

    当然这是一个猜测,快速查看源代码和一些vxworks shell断点可以确认这一点,我无法做到这一点,因为我无法访问vxworks .

    另外,请查看semMLib文档,了解有关递归使用互斥锁的一些文档 .

相关问题