并发与进程
pthread、mutex、atomic。
30 分钟
并发与进程
C 标准库本身线程支持有限(C11 <threads.h> 普及度不一),POSIX pthread 是 Linux/macOS 常见方案。对照 /roadmaps/c,本课介绍线程、互斥锁与原子操作入门。
学习目标
- 理解进程与线程的区别
- 用 pthread 创建线程并
join - 用 mutex 保护共享数据
- 了解
_Atomic的基本用法
核心概念
pthread 与互斥锁
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define NUM_THREADS 4
#define INCREMENTS 100000
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static long counter = 0;
static void *worker(void *arg) {
long id = (long)arg;
for (int i = 0; i < INCREMENTS; i++) {
pthread_mutex_lock(&mtx);
counter++;
pthread_mutex_unlock(&mtx);
}
printf("thread %ld done\n", id);
return NULL;
}
int main(void) {
pthread_t threads[NUM_THREADS];
for (long t = 0; t < NUM_THREADS; t++) {
if (pthread_create(&threads[t], NULL, worker, (void *)t) != 0) {
perror("pthread_create");
return 1;
}
}
for (int t = 0; t < NUM_THREADS; t++) {
pthread_join(threads[t], NULL);
}
printf("counter=%ld (expected %d)\n",
counter, NUM_THREADS * INCREMENTS);
/* C11 原子(可选) */
_Atomic int atomic_val = 0;
atomic_val++;
printf("atomic_val=%d\n", atomic_val);
return 0;
}
编译(Linux/macOS):
gcc -std=c11 -pthread concurrent.c -o concurrent
要点
| 概念 | 说明 |
|---|---|
| 进程 | 独立地址空间,fork/exec 创建 |
| 线程 | 共享地址空间,需同步 |
| mutex | 互斥锁,保护临界区 |
| 数据竞争 | 未同步的并发写是未定义行为 |
Windows 用 _beginthreadex 或 pthreads-win32 移植层;生产环境可选线程池库。
与 C++/Java 对照
| 方面 | C (pthread) | C++ | Java |
|---|---|---|---|
| 线程 API | pthread | std::thread | Thread / 虚拟线程 |
| 同步 | mutex、sem | mutex、atomic | 、Lock |