【Linux 线程与进程】线程与进程技术基础
目录
一、基本概念
1. 进程(Process)
2. 线程(Thread)
二、多进程与多线程的对比
三、多进程编程
1. 进程创建
2. 进程间通信(IPC)
四、多线程编程
1. 基本线程创建
2. 线程同步(互斥锁 + 条件变量)
3.线程的编译
五、选择策略与最佳实践
1. 优先选择多线程的场景
2. 优先选择多进程的场景
3. 混合使用
一、基本概念
1. 进程(Process)
进程是操作系统资源分配的基本单位,每个进程拥有独立的虚拟地址空间、文件描述符、信号处理等资源。
特性:
-
独立性:进程间资源隔离,崩溃不会直接影响其他进程46。
-
动态性:具有生命周期,通过系统调用(如
fork()
)创建,通过exec()
加载程序。
2. 线程(Thread)
线程是CPU调度的最小单位,属于同一进程的线程共享进程的全局内存、文件描述符等资源,但拥有独立的栈和程序计数器。
特性:
- 共享性:线程间可直接访问共享数据,但需同步机制(如互斥锁)避免竞态条件。
- 轻量级:创建和切换开销远小于进程。
二、多进程与多线程的对比
维度 | 多进程 | 多线程 |
---|---|---|
资源隔离 | 高(独立地址空间) | 低(共享地址空间) |
创建开销 | 高(需复制父进程资源) | 低(共享进程资源) |
通信方式 | 复杂(需IPC:管道、共享内存等) | 简单(通过共享内存) |
适用场景 | 高可靠性需求(如服务隔离) | 高并发I/O或计算密集型任务 |
三、多进程编程
1. 进程创建
-
通过
fork()
系统调用创建子进程,子进程复制父进程的资源(写时复制优化)。示例:
pid_t pid = fork();
if (pid == 0) { // 子进程代码
} else { // 父进程代码
}
-
进程退出后需由父进程调用
wait()
或waitpid()
回收资源,避免僵尸进程。
2. 进程间通信(IPC)
-
管道(Pipe):单向通信,适用于父子进程。
#include <stdio.h> #include <unistd.h> #include <sys/wait.h>int main() {int pipefd[2];char buffer[20];// 1. 创建管道if (pipe(pipefd) == -1) {perror("pipe");return 1;}// 2. 创建子进程pid_t pid = fork();if (pid == -1) {perror("fork");return 1;}if (pid == 0) { // 子进程close(pipefd[0]); // 关闭读端write(pipefd[1], "Hello from child", 16);close(pipefd[1]);} else { // 父进程close(pipefd[1]); // 关闭写端read(pipefd[0], buffer, sizeof(buffer));printf("Parent received: %s\n", buffer);close(pipefd[0]);wait(NULL); // 等待子进程结束}return 0; }
-
共享内存:高效数据共享,需配合信号量同步。
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/wait.h>#define SHM_SIZE 1024int main() {// 1. 创建共享内存int shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666);if (shmid == -1) {perror("shmget");return 1;}// 2. 映射到进程地址空间char *shm_ptr = (char*)shmat(shmid, NULL, 0);if (shm_ptr == (char*)-1) {perror("shmat");return 1;}pid_t pid = fork();if (pid == 0) { // 子进程sprintf(shm_ptr, "Child writes data");shmdt(shm_ptr); // 解除映射} else { // 父进程wait(NULL); // 等待子进程结束printf("Parent read: %s\n", shm_ptr);shmdt(shm_ptr);shmctl(shmid, IPC_RMID, NULL); // 删除共享内存}return 0; }
-
消息队列:结构化数据传输,支持多进程通信。
四、多线程编程
1. 基本线程创建
使用 pthread_create
创建线程,pthread_join
等待线程结束。
#include <stdio.h>
#include <pthread.h>void* thread_func(void* arg) {printf("Thread ID: %lu, Message: %s\n", pthread_self(), (char*)arg);return NULL;
}int main() {pthread_t tid1, tid2;char *msg1 = "Hello from Thread 1";char *msg2 = "Hello from Thread 2";pthread_create(&tid1, NULL, thread_func, msg1);pthread_create(&tid2, NULL, thread_func, msg2);pthread_join(tid1, NULL);pthread_join(tid2, NULL);return 0;
}
2. 线程同步(互斥锁 + 条件变量)
生产者-消费者模型是经典的同步问题,通过互斥锁保护共享资源,条件变量实现线程间协调。
#include <stdio.h>
#include <pthread.h>#define BUFFER_SIZE 5int buffer[BUFFER_SIZE];
int count = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_producer = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_consumer = PTHREAD_COND_INITIALIZER;void* producer(void* arg) {for (int i = 0; i < 10; i++) {pthread_mutex_lock(&mutex);while (count == BUFFER_SIZE) { // 缓冲区满,等待pthread_cond_wait(&cond_producer, &mutex);}buffer[count++] = i;printf("Produced: %d\n", i);pthread_cond_signal(&cond_consumer); // 通知消费者pthread_mutex_unlock(&mutex);}return NULL;
}void* consumer(void* arg) {for (int i = 0; i < 10; i++) {pthread_mutex_lock(&mutex);while (count == 0) { // 缓冲区空,等待pthread_cond_wait(&cond_consumer, &mutex);}int item = buffer[--count];printf("Consumed: %d\n", item);pthread_cond_signal(&cond_producer); // 通知生产者pthread_mutex_unlock(&mutex);}return NULL;
}int main() {pthread_t tid_producer, tid_consumer;pthread_create(&tid_producer, NULL, producer, NULL);pthread_create(&tid_consumer, NULL, consumer, NULL);pthread_join(tid_producer, NULL);pthread_join(tid_consumer, NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond_producer);pthread_cond_destroy(&cond_consumer);return 0;
}
3.线程的编译
# 编译多进程程序
gcc process_example.c -o process# 编译多线程程序(需链接 pthread 库)
gcc thread_example.c -o thread -lpthread
五、选择策略与最佳实践
1. 优先选择多线程的场景
- 需要频繁共享数据(如全局计数器)。
- 对延迟敏感的任务(如实时数据处理)。
2. 优先选择多进程的场景
- 需要高可靠性(如关键后台服务)。
- 需隔离不同任务(如防止内存泄漏扩散)。
3. 混合使用
在复杂系统中,可结合多进程与多线程。例如:
-
使用多进程部署多个服务实例。
-
每个服务实例内部使用多线程处理请求。