关注、星标公众号,直达精彩内容
正文一、多线程基础概念1. 什么是线程?线程是程序执行的最小单元,是进程中的一个独立执行路径。一个进程可以包含多个线程,这些线程共享进程的内存空间(如全局变量、堆内存),但每个线程有自己的栈空间(用于存储局部变量和函数调用信息)。
2. 线程与进程的区别特性
进程
线程
内存空间
独立的内存空间
共享进程的内存空间
资源开销
创建和销毁成本高
创建和销毁成本低
通信方式
需要进程间通信(IPC)
直接共享内存,通信更高效
上下文切换
切换成本高
切换成本低
稳定性
一个进程崩溃不会影响其他进程
一个线程崩溃可能导致整个进程崩溃
3. 为什么使用多线程?提高程序响应速度:例如在GUI程序中,主线程处理界面,子线程处理耗时任务。充分利用多核CPU:多线程可以并行执行,提升计算效率。简化复杂任务的开发:将任务分解为多个线程,逻辑更清晰。二、C语言多线程实现(POSIX线程库)1. POSIX线程库简介C语言本身不直接支持多线程,但通过POSIX线程库(pthread)可以实现多线程编程。该库是跨平台的,主要在Linux/Unix系统中使用,Windows下需使用Win32 API(本文以pthread为例)。
2. 基本函数函数
作用
pthread_create()
创建线程
pthread_join()
等待线程结束
pthread_exit()
终止当前线程
pthread_detach()
将线程设为分离状态(无需等待)
pthread_mutex_lock()
加锁(保护共享资源)
pthread_mutex_unlock()
解锁
pthread_cond_wait()
条件变量等待
pthread_cond_signal()
唤醒等待的线程
三、多线程编程入门示例1. 创建线程代码语言:javascript复制#include
#include
// 线程执行函数
void* thread_function(void* arg) {
int value = *(int*)arg;
printf("Hello from thread! Value: %d\n", value);
return NULL;
}
int main() {
pthread_t thread; // 定义线程标识符
int arg = 42; // 传递给线程的参数
// 创建线程
if (pthread_create(&thread, NULL, thread_function, &arg) != 0) {
perror("Failed to create thread");
return 1;
}
// 等待线程结束
pthread_join(thread, NULL);
printf("Main thread finished.\n");
return 0;
}
编译命令:
代码语言:javascript复制gcc -o thread_example thread_example.c -lpthread
运行结果:
代码语言:javascript复制Hello from thread! Value: 42
Main thread finished.
imageimage
2. 线程生命周期创建:pthread_create()运行:线程执行指定函数等待:pthread_join() 等待线程结束分离:pthread_detach() 释放线程资源终止:pthread_exit() 或线程函数返回四、线程同步机制1. 共享资源与数据竞争当多个线程同时访问共享资源(如全局变量)时,可能导致数据不一致。例如:
代码语言:javascript复制#include
#include
int counter = 0;
void* increment_counter(void* arg) {
for (int i = 0; i < 100000; i++) {
counter++; // 未保护的共享资源
}
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_create(&t1, NULL, increment_counter, NULL);
pthread_create(&t2, NULL, increment_counter, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Final counter value: %d\n", counter); // 预期值为200000,但实际可能小于该值
return 0;
}
imageimage
问题:counter++ 是非原子操作(读取-修改-写入),多个线程同时操作会导致数据竞争。
2. 互斥锁(Mutex)互斥锁用于保护共享资源,确保同一时刻只有一个线程访问。
代码语言:javascript复制#include
#include
int counter = 0;
pthread_mutex_t lock; // 定义互斥锁
void* increment_counter(void* arg) {
for (int i = 0; i < 100000; i++) {
pthread_mutex_lock(&lock); // 加锁
counter++;
pthread_mutex_unlock(&lock); // 解锁
}
return NULL;
}
int main() {
pthread_mutex_init(&lock, NULL); // 初始化互斥锁
pthread_t t1, t2;
pthread_create(&t1, NULL, increment_counter, NULL);
pthread_create(&t2, NULL, increment_counter, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&lock); // 销毁互斥锁
printf("Final counter value: %d\n", counter); // 输出200000
return 0;
}
imageimage
3. 条件变量(Condition Variable)条件变量用于线程间通信,当某个条件满足时唤醒等待的线程。
示例:生产者-消费者模型
代码语言:javascript复制#include
#include
#include
#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE];
int count = 0;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t not_empty = PTHREAD_COND_INITIALIZER;
pthread_cond_t not_full = PTHREAD_COND_INITIALIZER;
void* producer(void* arg) {
for (int i = 1; i <= 10; i++) {
pthread_mutex_lock(&lock);
while (count == BUFFER_SIZE) {
pthread_cond_wait(¬_full, &lock); // 缓冲区满时等待
}
buffer[count++] = i;
printf("Produced: %d\n", i);
pthread_cond_signal(¬_empty); // 通知消费者
pthread_mutex_unlock(&lock);
usleep(100000); // 模拟生产时间
}
return NULL;
}
void* consumer(void* arg) {
for (int i = 1; i <= 10; i++) {
pthread_mutex_lock(&lock);
while (count == 0) {
pthread_cond_wait(¬_empty, &lock); // 缓冲区空时等待
}
int item = buffer[--count];
printf("Consumed: %d\n", item);
pthread_cond_signal(¬_full); // 通知生产者
pthread_mutex_unlock(&lock);
usleep(100000); // 模拟消费时间
}
return NULL;
}
int main() {
pthread_t p, c;
pthread_create(&p, NULL, producer, NULL);
pthread_create(&c, NULL, consumer, NULL);
pthread_join(p, NULL);
pthread_join(c, NULL);
return 0;
}
imageimage
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
代码语言:javascript复制关注我的微信公众号,回复“C语言”免费领取300G编程资料。代码语言:javascript复制欢迎点赞、分享、推荐、留言。