在 C 语言中使用 C11 线程库

Jinku Hu 2023年10月12日
  1. 在 C 语言中使用 thrd_create 函数创建一个新线程并执行给定的例程
  2. 使用 thrd_join 函数等待 C 语言中的给定线程
在 C 语言中使用 C11 线程库

本文将解释几种如何在 C 语言中使用 C11 线程库的方法。

在 C 语言中使用 thrd_create 函数创建一个新线程并执行给定的例程

在标准的 C 语言规范中,对线程的支持迟迟没有出现,终于在 C11 中实现了。在此之前,POSIX 线程 API 被用作利用多线程编程的主要工具。由于 C11 提供了更标准的接口,可以在不依赖平台的情况下使用,因此建议使用 ISO 语言 API,而不要使用 POSIX 版本。尽管这两个 API 的功能原型不匹配,但主要功能大多相似。在下面的示例中,我们演示了一个简单的场景,其中启动了四个线程来执行 printHello 函数,然后在不加入主线程的情况下终止该线程。

thrd_create 接受三个参数,

  1. 第一个是指向线程标识符的指针。
  2. 第二个参数的类型为 thrd_start_t,对于函数指针原型而言,其名称仅为 typedef
  3. 第三个参数指定可以传递给函数的参数。

使用枚举值定义 thrd_create 的返回状态代码:thrd_successthrd_nomemthrd_error

#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#include <unistd.h>

#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif

void *printHello(void *thr_id) {
  long tid;
  tid = (long)thr_id;
  printf("Hello There! thread #%ld, pthread ID - %lu\n", tid, thrd_current());
  thrd_exit(EXIT_SUCCESS);
}

int main(int argc, char const *argv[]) {
  thrd_t threads[NUM_THREADS];
  int rc;
  long t;

  for (t = 0; t < NUM_THREADS; t++) {
    rc = thrd_create(&threads[t], (thrd_start_t)printHello, (void *)t);
    if (rc == thrd_error) {
      printf("ERORR; thrd_create() call failed\n");
      exit(EXIT_FAILURE);
    }
  }
  thrd_exit(EXIT_SUCCESS);
}

输出:

Hello There! thread 0, pthread ID - 140215498864384
Hello There! thread 1, pthread ID - 140215490471680
Hello There! thread 3, pthread ID - 140215473686272
Hello There! thread 2, pthread ID - 140215482078976

使用 thrd_join 函数等待 C 语言中的给定线程

thrd_joinpthread_join 函数的一个类比,它将阻塞当前线程,直到给定线程完成执行。它带有两个参数:线程标识符和 int 指针,表示如果用户提供有效地址,则可以选择存储返回状态代码的位置。如果在已经分离或联接的线程上调用 thrd_join,则结果是未定义的行为。该函数返回对应于 thrd_successthrd_error 的值。

下一个示例代码实现了四个线程递增 atomic_int 类型变量的情况。最后,等待其他线程完成的主线程将打印 counter 的最终总和值。

#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#include <unistd.h>

#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif

atomic_int counter = 0;

enum { MAX_ITER = 1000 };

void *printHello(void *thr_id) {
  long tid;
  tid = (long)thr_id;
  printf("thread %ld started incrementing ID - %lu\n", tid, thrd_current());

  for (int i = 0; i < MAX_ITER; ++i) {
    counter += 1;
  }

  return NULL;
}

int main(int argc, char const *argv[]) {
  thrd_t threads[NUM_THREADS];
  int rc;
  long t;

  for (t = 0; t < NUM_THREADS; t++) {
    rc = thrd_create(&threads[t], (thrd_start_t)printHello, (void *)t);
    if (rc == thrd_error) {
      printf("ERORR; thrd_create() call failed\n");
      exit(EXIT_FAILURE);
    }
  }

  for (t = 0; t < NUM_THREADS; t++) {
    thrd_join(threads[t], NULL);
  }
  printf("count = %d\n", counter);

  thrd_exit(EXIT_SUCCESS);
}

输出:

thread 0 started incrementing ID - 139729818216192
thread 2 started incrementing ID - 139729801430784
thread 3 started incrementing ID - 139729793038080
thread 1 started incrementing ID - 139729809823488
count = 4000
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 创始人。Jinku 在机器人和汽车行业工作了8多年。他在自动测试、远程测试及从耐久性测试中创建报告时磨练了自己的编程技能。他拥有电气/电子工程背景,但他也扩展了自己的兴趣到嵌入式电子、嵌入式编程以及前端和后端编程。

LinkedIn Facebook

相关文章 - C Thread