我在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 回答
在这种情况下,互斥体可能更快,因为相同的任务一次又一次地重复使用,而不涉及其他任务 . 我的猜测是互斥代码采用了一种快捷方式来启用递归互斥调用(即同一个任务需要两次相同的互斥锁) . 即使您的代码在技术上不是递归互斥,但代码可能使用相同的快捷方式,因为信号量所有者未被任何其他获取信号量的任务覆盖 .
换句话说,你这样做:
然后在步骤4中,semTake看到sem owner ==当前任务id(因为sem所有者在步骤1中设置并且从未更改为其他任何内容),因此它只是将信号量标记为已采用并快速跳出 .
当然这是一个猜测,快速查看源代码和一些vxworks shell断点可以确认这一点,我无法做到这一点,因为我无法访问vxworks .
另外,请查看semMLib文档,了解有关递归使用互斥锁的一些文档 .