Skip to content
📖 Auto 版 Modern C本书目录

第二十章:线程 ​

级别 3 -- 经验

使用 C 线程、互斥量和条件变量进行共享内存并发——以及为什么 Auto 的 Actor 模型使大部分这些变得不必要。

并发是 C 程序最容易出错的地方。数据竞争、死锁和微妙的内存排序错误以难以复现和修复而闻名。C11 引入了基于 POSIX 线程的标准线程 API。Auto 采取了根本不同的方法:具有隔离状态的 Actor 通过消息传递进行通信。


20.1 简单的线程间控制 ​

C11 提供了 thrd_create 和 thrd_join 用于线程管理:

c
// C 深入:线程创建
#include <threads.h>
#include <stdio.h>

int worker(void *arg) {
    int id = *(int *)arg;
    printf("Worker %d started\n", id);
    int sum = 0;
    for (int i = 0; i < 100; i++) {
        sum += i;
    }
    printf("Worker %d finished, sum = %d\n", id, sum);
    return 0;
}

int main(void) {
    thrd_t t1, t2;
    int id1 = 1, id2 = 2;

    thrd_create(&t1, worker, &id1);
    thrd_create(&t2, worker, &id2);

    thrd_join(t1, NULL);
    thrd_join(t2, NULL);
    return 0;
}

C 深入: C 线程共享整个地址空间。每个线程都可以读写每个全局变量。这使得数据竞争极其容易创建。线程函数必须返回 int(不是 POSIX 的 void*)。thrd_create 的参数以 void* 传递——这是类型错误的常见来源。

Auto 的方法。 Auto 使用 Actor 模型代替原始线程:

auto
// Auto:顺序执行(Actor 模型计划中)
fn worker(id int) {
    print("Worker", id, "started")
    var sum int = 0
    for i in 0..100 {
        sum = sum + i
    }
    print("Worker", id, "finished, sum =", sum)
}

fn main() {
    worker(1)
    worker(2)
}

基于 MIT 许可发布。