操作系统学习(六)——多线程
一、多线程
多线程(Multithreading)是操作系统和编程语言中实现并发的一种核心技术,它允许一个进程内并行地执行多个线程(轻量级进程)。
它广泛应用于 GUI 响应、服务器并发处理、计算密集型任务优化等场景。
线程是程序执行的最小单位,是进程中的执行路径。
一个进程可以包含多个线程,这些线程共享:
- 内存空间(代码段、数据段、堆);
- 文件描述符;
- 打开的资源;
但每个线程拥有独立的栈、程序计数器(PC)和寄存器。
特点:
- 提高程序并发性
可同时处理多个任务(如 UI + 下载); - 提升资源利用率
特别适合多核 CPU 并行计算; - 改进程序结构
逻辑清晰,例如用不同线程处理输入、处理、输出; - 响应更快
在 GUI 程序中避免界面卡顿(主线程负责UI,子线程执行耗时操作)。
二、单线程 vs 多线程
比较点 | 单线程 | 多线程 |
---|---|---|
并发能力 | 无 | 支持多个任务并发执行 |
CPU 利用率 | 低 | 高,尤其在多核 CPU 上 |
响应性 | 较差(容易卡顿) | 高,可边计算边响应 |
资源开销 | 低 | 中,开销小于多进程 |
编程复杂度 | 简单 | 较复杂(需处理同步问题) |
三、多线程线程的同步机制
在多线程中对共享资源操作时,需使用同步机制来防止竞争条件:
同步机制 | 描述 |
---|---|
互斥锁(mutex) | 一次只有一个线程进入临界区 |
条件变量 | 实现线程等待和通知 |
信号量 | 控制多个线程对资源的并发访问 |
屏障(barrier) | 等待所有线程到达后统一推进 |
原子变量 | 无需加锁实现简单同步 |
四、多线程的创建
1. C语言 POSIX
多线程:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>#define NUM_THREADS 5void* thread_func(void* arg)
{int id = *(int*)arg;printf("Thread %d is running.\n", id);free(arg); // 动态分配需释放return NULL;
}int main()
{pthread_t threads[NUM_THREADS];for (int i = 0; i < NUM_THREADS; ++i) {int* id = malloc(sizeof(int)); // 使用堆内存避免数据竞争*id = i;pthread_create(&threads[i], NULL, thread_func, id);}for (int i = 0; i < NUM_THREADS; ++i) {pthread_join(threads[i], NULL);}return 0;
}
2. C++11 多线程:
#include <iostream>
using namespace std;
#include <thread>
#include <vector>void thread_func(int id)
{cout << "Thread " << id << " is running." << endl;
}int main()
{const int NUM_THREADS = 5;vector<thread> threads;for (int i = 0; i < NUM_THREADS; ++i){threads.emplace_back(thread_func, i); // 创建并启动线程}for (auto& t : threads){t.join(); // 等待每个线程结束}return 0;
}
3. Python 中的多线程:
import threadingdef thread_func(id):print(f"Thread {id} is running.")threads = []
for i in range(5):t = threading.Thread(target=thread_func, args=(i,))threads.append(t)t.start()for t in threads:t.join()
五、线程池(Thread Pool)
为了避免频繁创建销毁线程的开销,可使用线程池:
- 预创建一组线程等待任务;
- 提交任务后由空闲线程执行;
- 常用于 Web服务器、爬虫、任务队列等。
六、多线程的问题
问题 | 描述 |
---|---|
竞态条件 | 多线程访问共享资源可能引发数据竞争 |
死锁 | 多线程互相等待资源导致系统僵死 |
资源争用 | 多线程争抢 CPU 或内存资源 |
上下文切换开销 | 线程切换需要保存/恢复状态,消耗 CPU 时间 |
可重入性问题 | 非线程安全函数被多个线程调用会出错 |
七、应用场景
场景 | 描述 |
---|---|
Web服务器 | 每个请求一个线程或线程池处理 |
GUI程序 | 主线程处理 UI,子线程处理后台逻辑 |
多核并行计算 | 将大任务分成多个线程分工计算 |
数据处理管道(流水线) | 每一步由一个线程负责,提高效率 |
异步 I/O | 使用线程避免阻塞主流程 |
八、多线程 vs 多进程
比较点 | 多线程 | 多进程 |
---|---|---|
资源开销 | 小,共享内存空间 | 大,各进程独立内存 |
创建销毁开销 | 小,速度快 | 大,开销高 |
通信方式 | 共享变量 | IPC机制(管道、共享内存等) |
稳定性 | 稍差,一个线程崩溃可能影响进程 | 高,互不影响 |
并发性能 | 高,适合密集计算 | 高,适合任务隔离 |