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

时间:2014-02-24 16:25:59

标签: c++ mutex semaphore vxworks

我在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 个答案:

答案 0 :(得分: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文档,了解有关递归使用互斥锁的一些文档。