行,这一块我直接给你一份“能从 0 写到生产级”的 pthread 全量体系,不搞碎片,直接一屏尽量塞满核心知识 + 可运行代码骨架。你看完基本可以自己写多线程程序 + 同步原语 + 调试了。 --- # 一、pthread 是什么(本质) POSIX Threads(pthread)= 用户态 API + 内核线程(Linux NPTL实现) 本质模型: * 每个 pthread ≈ 一个内核调度实体(LWP) * 共享:地址空间 / 全局变量 / 堆 * 独立:栈 / 寄存器 / 线程ID / 调度状态 --- # 二、最小可运行 pthread 程序(核心骨架) ```c #include #include void* thread_func(void* arg) { int val = *(int*)arg; printf("Thread got: %d\n", val); return (void*) (long)(val * 2); } int main() { pthread_t tid; int arg = 10; pthread_create(&tid, NULL, thread_func, &arg); void* ret; pthread_join(tid, &ret); printf("Thread return: %ld\n", (long)ret); return 0; } ``` 编译: ```bash gcc main.c -o main -pthread ``` 关键点: * pthread_create → 创建线程 * pthread_join → 回收线程(类似 wait) * 函数签名必须:`void* (*)(void*)` --- # 三、线程创建:pthread_create(核心接口) ```c int pthread_create( pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg ); ``` 关键理解: * thread:输出线程ID * attr:线程属性(栈大小 / detached等) * start_routine:线程入口函数 * arg:传入参数(只能一个 → 用 struct) --- # 四、线程终止(3种方式) ### 1. return ```c return value; ``` ### 2. pthread_exit ```c pthread_exit((void*)value); ``` ### 3. 主线程退出影响 ```c exit(0); // 杀死整个进程 pthread_exit(0); // 主线程结束,但子线程继续 ``` --- # 五、pthread_join vs detach(非常重要) ### join(默认) ```c pthread_join(tid, &ret); ``` * 阻塞等待线程结束 * 回收资源(必须,否则泄漏) --- ### detach(分离线程) ```c pthread_detach(tid); ``` 或: ```c pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); ``` 特点: * 自动回收 * 不能 join * 常用于后台线程 --- # 六、线程属性 pthread_attr_t(控制线程行为) ```c pthread_attr_t attr; pthread_attr_init(&attr); // 设置栈大小 pthread_attr_setstacksize(&attr, 1024 * 1024); // 设置 detached pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_create(&tid, &attr, func, NULL); pthread_attr_destroy(&attr); ``` --- # 七、线程同步核心:为什么需要? 多个线程: * 共享内存 → 数据竞争(race condition) * CPU乱序 / 编译优化 → 不可预测 必须同步! --- # 八、互斥锁(Mutex)——最核心 ## 使用流程 ```c pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&lock); // 临界区 pthread_mutex_unlock(&lock); ``` --- ## 完整例子(避免竞态) ```c #include #include int counter = 0; pthread_mutex_t lock; void* worker(void* arg) { for (int i = 0; i < 100000; i++) { pthread_mutex_lock(&lock); counter++; pthread_mutex_unlock(&lock); } return NULL; } int main() { pthread_t t1, t2; pthread_mutex_init(&lock, NULL); pthread_create(&t1, NULL, worker, NULL); pthread_create(&t2, NULL, worker, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); printf("counter = %d\n", counter); pthread_mutex_destroy(&lock); } ``` --- ## mutex 本质(你要理解这个) * lock → 内核futex(用户态自旋 + 内核阻塞) * 竞争少:用户态解决 * 竞争多:进入内核 sleep --- # 九、读写锁(rwlock) ```c pthread_rwlock_t rwlock; pthread_rwlock_init(&rwlock, NULL); pthread_rwlock_rdlock(&rwlock); // 多读 pthread_rwlock_wrlock(&rwlock); // 独占写 pthread_rwlock_unlock(&rwlock); ``` 适合: * 读多写少 --- # 十、条件变量(Condition Variable)——线程通信核心 ## 模型:生产者消费者 ```c pthread_mutex_t lock; pthread_cond_t cond; int ready = 0; void* consumer(void* arg) { pthread_mutex_lock(&lock); while (!ready) { pthread_cond_wait(&cond, &lock); } printf("Consumed\n"); pthread_mutex_unlock(&lock); } ``` --- ### 生产者: ```c pthread_mutex_lock(&lock); ready = 1; pthread_cond_signal(&cond); pthread_mutex_unlock(&lock); ``` --- ### 核心语义(重点) ```c pthread_cond_wait(&cond, &lock); ``` 等价于: 1. unlock(lock) 2. sleep 3. 被唤醒 4. lock(lock) ⚠️ 必须 while 而不是 if(防止虚假唤醒) --- # 十一、信号量(POSIX sem) ```c #include sem_t sem; sem_init(&sem, 0, 1); // 1 = mutex sem_wait(&sem); sem_post(&sem); ``` --- # 十二、自旋锁(spinlock) ```c pthread_spinlock_t spin; pthread_spin_init(&spin, PTHREAD_PROCESS_PRIVATE); pthread_spin_lock(&spin); // busy wait pthread_spin_unlock(&spin); ``` 适合: * 临界区极短 * 不想进入内核 --- # 十三、线程局部存储(TLS) ```c pthread_key_t key; pthread_key_create(&key, NULL); pthread_setspecific(key, value); void* val = pthread_getspecific(key); ``` 本质: * 每个线程一份变量(类似 __thread) --- # 十四、线程取消(高级) ```c pthread_cancel(tid); ``` 线程需要: ```c pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); ``` --- # 十五、常见坑(你必须知道) 1. ❌ 传栈变量地址 ```c int x; pthread_create(..., &x); // 线程可能读到脏数据 ``` ✔ 解决: * malloc / struct --- 2. ❌ 忘记 join → 内存泄漏 --- 3. ❌ 死锁 ```c T1: lock(A) → lock(B) T2: lock(B) → lock(A) ``` --- 4. ❌ double lock --- 5. ❌ cond 没用 while --- # 十六、完整“工业级”线程模型(模板) ```c typedef struct { int id; pthread_mutex_t* lock; } Task; void* worker(void* arg) { Task* t = (Task*)arg; pthread_mutex_lock(t->lock); printf("Thread %d working\n", t->id); pthread_mutex_unlock(t->lock); return NULL; } int main() { pthread_t tids[4]; pthread_mutex_t lock; pthread_mutex_init(&lock, NULL); Task tasks[4]; for (int i = 0; i < 4; i++) { tasks[i].id = i; tasks[i].lock = &lock; pthread_create(&tids[i], NULL, worker, &tasks[i]); } for (int i = 0; i < 4; i++) { pthread_join(tids[i], NULL); } pthread_mutex_destroy(&lock); } ``` --- # 十七、你可以继续往下学的方向(建议) 如果你要深入(你现在这个水平完全可以): * pthread + epoll → 高性能服务器 * 线程池实现(非常关键) * work queue / task queue * lock-free(CAS + 原子操作) * 内存模型(happens-before) --- 如果你要,我下一步可以直接给你: 1. 手写线程池(工业级实现) 2. pthread + epoll 写一个 Web Server 3. 从 pthread 过渡到 C++ std::thread / async(对比底层) 你现在这个进度,已经在往系统级工程走了,这块搞透基本就是“写操作系统级程序”的门槛。