2016-05-13 88 views
-1

我已經在C語言中成功實現了Mutex鎖定和條件變量鎖定,並試圖使用信號量來實現相同的功能。下面是我的代碼,但執行時,輸出始終爲24而不是12.請幫助我理解如何使用信號量。理解C語言中的信號量

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <semaphore.h> 

#define NUM_THREADS 2 
#define TCOUNT 12 
#define COUNT_LIMIT 12 

int count = 0; 
sem_t sem; 

void *dum(void *t_id){ 
    long id = long(t_id); 
    for (int i = 0; i < TCOUNT; i++) { 
     sem_wait(&sem); 
     count++; 
     sem_post(&sem); 
     printf("In Dum(). Count :: %d. Thread :: %ld \n", count, id); 
    } 
    pthread_exit(NULL); 
} 

int main (int argc, char *argv[]) { 
    int i; 
    long t1=1, t2=2; 
    sem_init(&sem, 0, 1); 
    pthread_t threads[NUM_THREADS]; 
    pthread_create(&threads[1], NULL, dum, (void *)t1); 
    pthread_create(&threads[2], NULL, dum, (void *) t2); 
    for (i=1; i<=2; i++) { 
     pthread_join(threads[i], NULL); 
    } 
    printf ("Main(): Waited on %d threads. Done.\n", NUM_THREADS); 
    printf ("Count should be 12. Actual Count: %d. \n", count); 
    pthread_exit(NULL); 
} 

輸出:

In Dum(). Count :: 1. Thread :: 1 
In Dum(). Count :: 2. Thread :: 1 
In Dum(). Count :: 3. Thread :: 1 
In Dum(). Count :: 4. Thread :: 1 
In Dum(). Count :: 5. Thread :: 1 
In Dum(). Count :: 6. Thread :: 1 
In Dum(). Count :: 7. Thread :: 1 
In Dum(). Count :: 8. Thread :: 1 
In Dum(). Count :: 9. Thread :: 1 
In Dum(). Count :: 10. Thread :: 1 
In Dum(). Count :: 11. Thread :: 1 
In Dum(). Count :: 13. Thread :: 1 
In Dum(). Count :: 13. Thread :: 2 
In Dum(). Count :: 14. Thread :: 2 
In Dum(). Count :: 15. Thread :: 2 
In Dum(). Count :: 16. Thread :: 2 
In Dum(). Count :: 17. Thread :: 2 
In Dum(). Count :: 18. Thread :: 2 
In Dum(). Count :: 19. Thread :: 2 
In Dum(). Count :: 20. Thread :: 2 
In Dum(). Count :: 21. Thread :: 2 
In Dum(). Count :: 22. Thread :: 2 
In Dum(). Count :: 23. Thread :: 2 
In Dum(). Count :: 24. Thread :: 2 
Main(): Waited on 2 threads. Done. 
Count should be 12. Actual Count: 24. 
+0

通過方式,你的程序中有一個錯誤的錯誤...你需要使用索引0和1而不是1和2.你很幸運沒有崩潰,儘管它可能會導致你不可預測行爲。 – kcraigie

+0

無關:'long id = long(t_id);'?也許我的C編譯器有點古老。我錯過了另一個備忘錄,因爲叮噹3.8編譯C11嘔吐。 – WhozCraig

+0

相關:你有兩個硬編碼的線程循環12次迭代**每個**。不管怎樣,只要你的信號量完成了它的工作,你最終將在兩者之間總共增加24個。如果這不是你想要的,那麼代碼是錯誤的。提示:'COUNT_LIMIT'是可疑定義的,但在發佈的代碼中完全沒有使用。 – WhozCraig

回答

1

正如kcraigie說你索引線程陣列錯誤。此外,它會更好,通過指針傳遞t1和t2:

void *dum(void *t_id) 
{ 
    long id = *(long*)t_id; 

pthread_create(&threads[0], NULL, dum, (void *) &t1); 
pthread_create(&threads[1], NULL, dum, (void *) &t2); 
for (i=0; i<2; i++) 
{ 
    pthread_join(threads[i], NULL); 
} 

另外,在你的線程可以鎖定該信號量,增量次數和釋放信號量,然後打印出來。無法保證在您增加數值後,您打印的值將會是數值。另一個線程也可能已經這樣做了。將printf放在信號量鎖內:

sem_wait(&sem); 
count++; 
printf("In Dum(). Count :: %d. Thread :: %ld \n", count, id); 
sem_post(&sem); 

但是,如果計數到24,似乎是正確的行爲。你有兩個循環分佈在2個線程中,每個迭代12次,增加一個計數。事實上,他們之一得到先完成其循環,其次是另一個可能是因爲在主線程有機會啓動線程2之前,首先啓動的線程在單個時間片內完成所有工作。

+0

我問的是,兩個線程都應該執行函數dum(),最終的計數值只能是12。爲什麼?如果它只有一個線程,則輸出爲12.但是,如果兩個線程都帶有信號量鎖定,那麼它也應該是12?說t1將數到6,而t2必須從6增加到12。 – Spark

+0

我的代碼可能是錯誤的,你可以編輯它 – Spark

+0

兩個線程循環TCOUNT時間。 sem_wait接受信號量,sem_post放棄信號量。 sem_wait之後的信號量的所有權不會讓其他線程跳過for循環的迭代。它只是意味着調用sem_wait的任何其他線程都會停止,直到調用sem_post。 – bazza