在 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