2014-02-24 99 views
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 ms。這是可以理解的,因爲二進制信號量是輕量級的,並沒有像互斥體(優先級反轉,所有權等)的許多功能。

但是,我刪除了一個任務並運行上述程序(沒有爭用)。由於沒有爭用,任務t1只是獲取互斥鎖,執行臨界區然後釋放互斥鎖。與二進制信號相同。
對於定時,互斥量我得到了3.35毫秒和二進制信號量4毫秒。

我很驚訝地看到互斥體在沒有爭用時比二進制信號量更快。
這是預期嗎?或者我錯過了什麼?

任何幫助表示讚賞。 !

+0

我認爲(但不確定)這種測量線程同步機制的方式不會給你正確的結果,因爲定時器還會跟蹤等待互斥鎖的時間。這不僅取決於互斥體和信號量的實現,還取決於操作系統將時隙分配給程序的方式。這在每次運行時都可能會有所不同。你有多少次試過這個和多久? – Excelcius

+0

我已經跑了20次,結果一致。我在我的控制器的一個空閒內核上運行這個程序,以便這個任務不會受到當前內核中已經運行的任務的干擾。 –

+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所有者==當前任務的ID(因爲SEM業主在步驟1中設置並沒有改變,以其他任何東西),所以它只是標記了信號量並迅速跳出。

當然這是一個猜測,快速查看源代碼和某些vxworks shell斷點可以證實這一點,這是我無法做到的,因爲我無法再訪問vxworks。

另外看一下關於遞歸使用互斥鎖的一些文檔的semMLib文檔。

+0

克里斯,你真棒。非常好的解釋。即使我相信同樣的事情正在發生。它正在得到優化,因爲semOwner每次都是一樣的。謝啦 ! –