【问题标题】:Understanding Semaphore in C理解 C 中的信号量
【发布时间】:2016-05-13 04:34:49
【问题描述】:

我已经成功地在 C 中实现了互斥锁和条件变量锁,并尝试使用信号量来实现相同的目标。下面是我的代码,但是执行时,输出总是24而不是12。请帮助我理解如何使用信号量。

#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 和 1 而不是 1 和 2。你很幸运,它不是崩溃,尽管它可能会导致您出现不可预知的行为。
  • 无关:long id = long(t_id); ?也许我的 C 编译器有点古老了。我是否错过了另一个备忘录,因为编译 C11 的 clang 3.8 对此感到厌烦。
  • 相关:您有两个线程被硬编码为循环 12 次迭代每个。一种或另一种方式,只要你的信号量完成它的工作,你最终会在两者之间总共有 24 个增量。如果这不是您想要的,那么代码是错误的。提示:COUNT_LIMIT 的定义可疑,但在发布的代码中完全未使用。
  • 程序几乎按原样运行(输出方面),您将i 计数到12 两次,所以count 将是i*224
  • @Serdalis:如何使用信号量让两个线程只运行到 12 个?

标签: c mutex semaphore


【解决方案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);
}

同样在你的线程中你锁定信号量,增加计数并释放信号量,然后你打印它。无法保证您打印出的值将是您增加后的 count 值。另一个线程可能也已经这样做了。将 printf 放入信号量锁中:

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

但否则数到 24 似乎是正确的行为。您有两个循环分布在 2 个线程中,每个线程迭代 12 次,加一计数。它们中的一个先完成循环然后另一个完成的事实可能是因为首先启动的线程在主线程有机会启动线程 2 之前在一个时间片内完成了所有工作。

【讨论】:

  • 我要问的是,两个线程都应该执行函数dum(),最终的计数值必须只有12。为什么?如果只有一个线程,则输出为 12。但是两个线程都使用信号量锁,它也应该是 12 对吧?假设 t1 将计数到 6,而 t2 必须从 6 开始计数到 ​​12。
  • 两个线程都循环了 TCOUNT 次。 sem_wait 获取信号量,sem_post 放弃信号量。 sem_wait 之后信号量的所有权不会神奇地使另一个线程跳过其 for 循环的迭代。它只是意味着任何其他调用 sem_wait 的线程都会停止,直到 sem_post 被调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-23
  • 2011-01-29
相关资源
最近更新 更多