C 中的 PThreads,线程 ID 是如何生成的,为什么它们交替出现

PThreads in C, how are thread-IDs generated, why they alternate

我正在尝试使用 pthread_create() 创建 (3) 个线程,并按顺序打印线程编号和 ID,进行 (5) 次迭代。

请原谅我的代码,我是 C 的新手,但在打印我的线程创建时我看到了一个奇怪的模式。例如,我想要的输出是:

Iteration: 1 of 5

        Thread 1 (ID: 140671542023744)
        Thread 2 (ID: 140671533631040)
        Thread 3 (ID: 140671525238336)

Iteration: 2 of 5

        Thread 1 (ID: 140671542023744)
        Thread 2 (ID: 140671533631040)
        Thread 3 (ID: 140671525238336)

Iteration: 3 of 5

        Thread 1 (ID: 140671542023744)
        Thread 2 (ID: 140671533631040)
        Thread 3 (ID: 140671525238336)

Iteration: 4 of 5

        Thread 1 (ID: 140671542023744)
        Thread 2 (ID: 140671533631040)
        Thread 3 (ID: 140671525238336)

Iteration: 5 of 5

        Thread 1 (ID: 140671542023744)
        Thread 2 (ID: 140671533631040)
        Thread 3 (ID: 140671525238336)

我的实际输出是:

Iteration: 1 of 5

        Thread 1 (ID: 140671542023744)
        Thread 2 (ID: 140671533631040)
        Thread 3 (ID: 140671525238336)

Iteration: 2 of 5

        Thread 1 (ID: 140671525238336) <-- Order starts reversing here for some reason
        Thread 2 (ID: 140671533631040)
        Thread 3 (ID: 140671542023744)

Iteration: 3 of 5

        Thread 1 (ID: 140671542023744)
        Thread 2 (ID: 140671533631040)
        Thread 3 (ID: 140671525238336)

Iteration: 4 of 5

        Thread 1 (ID: 140671525238336)
        Thread 2 (ID: 140671533631040)
        Thread 3 (ID: 140671542023744)

Iteration: 5 of 5

        Thread 1 (ID: 140671542023744)
        Thread 2 (ID: 140671533631040)
        Thread 3 (ID: 140671525238336)

非常感谢您的建议。这让我发疯。我的代码贴在下面:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

pthread_t threads[3];
pthread_mutex_t mutex;

void * printThread(void * arg) {
  pthread_t id = pthread_self(); // Get pthread ID
  
  printf("\t\tThread %d (ID: %ld)\n", arg + 1, id); // Print thread creation and ID, account for zero index
  
  return NULL;
}

int main(void) {
  int i, j;
  int error;
  
  if (pthread_mutex_init( & mutex, NULL) != 0) {
    printf("\n Error: pthread_mutex_init failure. [%s]\n", strerror(error));
    return 1;
  } // Catch and print pthread_mutex_init error

  printf("Begin multithreading...\n");

  /* Create and print (3) threads by ID, for (5) iterations */
  for (i = 0; i < 5; i++) {
    printf("\t\nIteration: %d of 5\n\n", i + 1);
    for (j = 0; j < 3; j++) {
      error = pthread_create( & (threads[j]), NULL, & printThread, (void * ) j); // Create new thread
      if (error != 0)
        printf("\nError: pthread_create failure. [%s]\n", strerror(error));
      sleep(2);
    } // Catch and print pthread_create error
    /* Syncrhonize threads */
    pthread_join(threads[0], NULL);
    pthread_join(threads[1], NULL);
    pthread_join(threads[2], NULL);
  }

  printf("\nMultithreading complete.\n");

  /* Cleanup threads and mutex */
  pthread_exit( & threads);
  pthread_mutex_destroy( & mutex);

  return 0;
}

pthreads 是一个非常不透明和通用的 API,因此使用 pthreads API 的应用程序代码可以很容易地移植到尽可能多的(通常是截然不同的)平台上。

作为不透明哲学的一部分,pthreads 对 pthread_create() 返回的 ID 值的唯一限制是每个有效(即 not-yet-joined)线程的 ID 在尊重方面是唯一的到进程中的所有其他有效线程。除此之外,所有行为都留给平台的 pthreads 实现来处理,但它认为合适。

鉴于此,我认为发布的代码中没有任何错误。唯一的错误是假设 pthread_create() 返回的 ID 应该或将遵循一些超出 thread-ID-uniqueness 的附加规则——这不是一个有效的假设。

回答了我自己的问题。我能够通过从线程数组中打印它们来绕过我的线程创建的错误排序,而不是从我的 pthread 创建中的函数中打印出来。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int thread;
pthread_t threads[3]; // Initialize thread array
pthread_mutex_t mutex;

void * printThread() {
  pthread_mutex_lock( & mutex); // Lock code

  pthread_t tid = pthread_self(); // Get thread

  printf("\nThread %d (thread-id: %ld) created successfully.", thread + 1,
    tid); // Print thread creation, account for zero index

  pthread_mutex_unlock( & mutex); // Unlock code

  return NULL;
}

int main(void) {
  int iteration;
  int error;

  if (pthread_mutex_init( & mutex, NULL) != 0) {
    printf("\n Error: pthread_mutex_init failure. [%s]\n", strerror(error));
    return 1;
  } // Catch and print pthread_mutex_init error

  printf("Begin multithreading...\n");

  /* Create and print three (3) threads by thread-id */
  for (thread = 0; thread < 3; thread++) {
    error = pthread_create( & (threads[thread]), NULL, & printThread, NULL); // Create new thread
    sleep(1); // Necessary to ensure proper order
    if (error != 0)
      printf("\nError: pthread_create failure. [%s]\n", strerror(error));
  } // Catch and print pthread_create error

  /* Synchronize threads */
  pthread_join(threads[0], NULL);
  pthread_join(threads[1], NULL);
  pthread_join(threads[2], NULL);

  /* Print three (3) threads, in turn, for five (5) iterations */
  for (iteration = 0; iteration < 5; iteration++) {
    printf("\n\n\tIteration: %d of 5 - \n", iteration + 1); // Account for zero index
    for (thread = 0; thread < 3; thread++) {
      printf("\n\t\tThread %d (thread-id: %ld)", thread + 1,
        threads[thread]); // Print threads in turn, account for zero index
      sleep(1); // Sleep to simulate thread step
    }
  }

  printf("\n\nMultithreading complete.\n");

  /* Cleanup mutex and threads */
  pthread_mutex_destroy( & mutex);
  pthread_exit( & threads);

  return 0;
}