【问题标题】:Pthread_Create in C leads to strange outputC中的Pthread_Create导致奇怪的输出
【发布时间】:2014-04-07 23:45:47
【问题描述】:

这是我的代码:

int BufferSize = 3;
int buffer[3] = {0,0,0};

int producer_cursor = 0;
int consumer_cursor = 0;

sem_t empty, mutex, full;

void* Producer(void *arg)
{

    sem_wait(&empty);
    sem_wait(&mutex);

    printf("producer thread: #%d in critical setion\n", *((int*) arg));
    int j;
    for (j=0;j<BufferSize;j++) {
        printf("%d", buffer[j]);
    }
    printf("\n");
    buffer[producer_cursor] = 1;
    producer_cursor = (++producer_cursor) % 3;

    for (j=0;j<BufferSize;j++) {
        printf("%d", buffer[j]);
    }
    printf("\n");
    sem_post(&full);
    sem_post(&mutex);
}

void * Consumer(void* arg)
{
   sem_wait(&full);
   sem_wait(&mutex);    

   printf("consumer thread: #%d in critical setion\n", *((int*) arg));
   int j;
   for (j=0;j<BufferSize;j++) {
      printf("%d", buffer[j]);
   }
   printf("\n");

   buffer[consumer_cursor] = 0;
   consumer_cursor = (++consumer_cursor) % 3;
   printf("after change\n");
   for (j=0;j<BufferSize;j++) {
       printf("%d", buffer[j]);
   }
   printf("\n");

   sem_post(&empty);
   sem_post(&mutex);
}

void main(int argc, char * argv[])
{
   int n; 
   pthread_t *threads;

   sem_init(&mutex, 0, 1);
   sem_init(&empty, 0, 3);
   sem_init(&full, 0, 0);   

   pthread_t consumers[NUM_COMSUMERS];
   pthread_t producers[NUM_PRODUCERS];

   int i;
   for (i = 0; i < NUM_COMSUMERS; i++) {
       pthread_create(consumers+i, NULL, Consumer, &i);
   }
   for (i = 0; i < NUM_PRODUCERS; i++) {
       pthread_create(producers+i, NULL, Producer, &i);
   }
   for (i = 0; i < NUM_COMSUMERS; i++) {
       pthread_join(consumers[i], NULL);
   }
   for (i = 0; i < NUM_PRODUCERS; i++) {
       pthread_join(producers[i], NULL);
   }
}

我得到的输出是:

producer thread: #1 in critical setion
000
100
consumer thread: #4 in critical setion
100
after change
000
producer thread: #0 in critical setion
000
010
consumer thread: #1 in critical setion
010
after change
000
producer thread: #1 in critical setion
000
001
producer thread: #2 in critical setion
001
101
consumer thread: #2 in critical setion
101
after change
100
consumer thread: #2 in critical setion
100
after change
000
producer thread: #2 in critical setion
000
010
consumer thread: #4 in critical setion
010
after change
000

结果是预期的,除了计数应该在 0 到 4 之间,而在这种情况下它没有“#3”。每次运行程序时,“#”都会改变。有时甚至只显示“#0”和“#1”。

【问题讨论】:

    标签: c multithreading operating-system producer-consumer


    【解决方案1】:

    pthread_create 的最后一个参数是问题所在。您将指针传递给i,但i 的值会随着主循环的执行而改变。当您的线程执行打印并且您尊重指针时,不能保证i 仍然是0(或123)。

    试试这个简单的改变;它会给你预期的结果:

    int i;
    int id[4] = { 1, 2, 3, 4 };
    for (i = 0; i < NUM_COMSUMERS; i++) {
        pthread_create(consumers+i, NULL, Consumer, id + i);
    }
    for (i = 0; i < NUM_PRODUCERS; i++) {
        pthread_create(producers+i, NULL, Producer, id + i);
    }
    

    以上假设NUM_CONSUMERSNUM_PRODUCERS 是4,它需要重新设计以使其更通用。

    或者,您不必传入指针,您可以执行以下操作:

    for (i = 0; i < NUM_COMSUMERS; i++) {
        pthread_create(consumers+i, NULL, Consumer, (void *)i);
    }
    for (i = 0; i < NUM_PRODUCERS; i++) {
        pthread_create(producers+i, NULL, Producer, (void *)i);
    }
    

    在你的线程中,不要取消引用 arg,只需将其转换为 int

    printf("producer thread: #%d in critical section\n", (int)arg);
    

    和:

    printf("consumer thread: #%d in critical section\n", (int)arg);
    

    注意:在 64 位系统上,您将收到在指针和 int 之间转换的警告。

    【讨论】:

    • 非常感谢!我明白现在出了什么问题。但是,当我尝试第二种方法时,它不起作用。它给了我一个分段错误。
    • @user2895478:我稍微更新了帖子以阐明与第二种方法相关的更改。我确实对其进行了测试并得到了预期的结果。正如我所指出的,你可以通过指针传递一个值,只要确保你没有在你的线程代码中取消引用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多