c - 用线程模拟火车

标签 c multithreading pthreads

编辑:我认为我做错了什么,因为当我编译并运行我的二进制文件两次时,我得到不同的输出..

我试图通过 pthread 理解线程,所以我编写了一些代码来模拟火车在桥上通过(桥一次只能处理 2 列火车)

我设法用这样的代码一次只让一列火车过桥:

#include <pthread.h>
#include <stdio.h>
#include <time.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void    *train()
{
  int   km;
  static int    t = 0;

  km = 1;
  while (km != 10)
    {
      printf("I'm at %02d km\n", km++);
      sleep(1);
      if (km == 2)
        pthread_mutex_lock(&mutex);
      if (km == 4)
        pthread_mutex_unlock(&mutex);
    }
}

int     main()
{
  pthread_t     train1;
  pthread_t     train2;
  pthread_t     train3;

  pthread_create(&train1, NULL, train, NULL);
  pthread_create(&train2, NULL, train, NULL);
  pthread_create(&train3, NULL, train, NULL);

  pthread_join(train1, NULL);
  pthread_join(train2, NULL);
  pthread_join(train3, NULL);
}

这个工作完美(或者我做错了什么,如果是的话请告诉我)

然后我尝试了 2 列火车可以同时通过桥的情况。

#include <pthread.h>
#include <stdio.h>
#include <time.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void    *train()
{
  int   km;
  static int    t = 0;

  km = 1;
  while (km != 30)
    {
      printf("I'm at %02d km\n", km++);
      sleep(1);
      if (km == 2 && t <= 2)
        {
          ++t;
          pthread_mutex_lock(&mutex);
        }
      if (km == 4)
        {
          t--;
          pthread_mutex_unlock(&mutex);
        }
    }
}

int     main()
{
  pthread_t     train1;
  pthread_t     train2;
  pthread_t     train3;
  pthread_t     train4;

  pthread_create(&train1, NULL, train, NULL);
  pthread_create(&train2, NULL, train, NULL);
  pthread_create(&train3, NULL, train, NULL);
  pthread_create(&train4, NULL, train, NULL);

  pthread_join(train1, NULL);
  pthread_join(train2, NULL);
  pthread_join(train3, NULL);
  pthread_join(train4, NULL);
}

所以我在桥上使用静态整数将我的火车“限制”为 2,但这实际上不起作用,我不明白为什么..

我的 4 列火车正在开动,然后 2 列继续上车,另外 2 列等待,当第 2 列离开桥时,只有另一列继续前进,最后一列等到第 ​​3 列离开桥去。 .

实际上,我希望有 4 列火车开行,2 列在桥上,2 列等待,当 2 列第一个离开桥时,另外 2 列在桥上。

很抱歉,它有点长,但我想它需要理解。

感谢您的帮助!

最佳答案

您的代码的问题在于,所有 pthread_mutex_lock(&mutex); 所做的就是等到 mutex 不再被锁定,然后再锁定它。它实际上并不检查 t 的值是什么。

您真正要寻找的是条件变量:

#include <pthread.h>
#include <stdio.h>
#include <time.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void    *train()
{
    int   km;
    static int t = 0;

    km = 1;
    while (km != 30)
    {
        printf("I'm at %02d km\n", km);

        // If we've reached the bridge, wait until less than two trains are on it.
        if (km == 2)
        {
            pthread_mutex_lock(&mutex);
            while (t == 2) { // To be read as: "While two trains are on the bridge, wait."
                pthread_cond_wait(&cond, &mutex);
            }
            ++t; // Put this train onto the bridge.
            pthread_mutex_unlock(&mutex);
        }

        // Leave the bridge.
        if (km == 4)
        {
            pthread_mutex_lock(&mutex);
            --t; // Take this train off the bridge.
            pthread_cond_signal(&cond); // Signal another train to enter.
            pthread_mutex_unlock(&mutex);
        }

        // Move forward 1 km.
        sleep(1);
        ++km;
    }
}

int     main()
{
    pthread_t     train1;
    pthread_t     train2;
    pthread_t     train3;
    pthread_t     train4;

    pthread_create(&train1, NULL, train, NULL);
    pthread_create(&train2, NULL, train, NULL);
    pthread_create(&train3, NULL, train, NULL);
    pthread_create(&train4, NULL, train, NULL);

    pthread_join(train1, NULL);
    pthread_join(train2, NULL);
    pthread_join(train3, NULL);
    pthread_join(train4, NULL);
}

if (km == 4) 位中额外锁定和解锁的要点是确保没有多个线程试图更改/检查 的值>t 一次。 (多个线程同时访问同一个变量通常会导致非常错误的行为!)

关于c - 用线程模拟火车,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28690753/

相关文章:

linux-kernel - 调度程序如何看到Linux上的pthreads

c - 错误消息 "undefined reference for ` CPU_ZERO'”

c++ - C++ 是否允许 VLA 作为函数参数

c - 空白行段。错误(自己写shell)

php - 如何在每个线程的PHP扩展中封装全局变量?

c - 确保不会丢失 cond 信号的安全方法

使用 pthreads 的 PHP 多线程,类未加载到 Thread 实例中

c - "else"之前的预期主表达式

c - 如何通过cygwin在windows中编译telegram-cli?

c - 我如何要求 OpenMP 在每次运行程序时只创建一次线程?