Linux 多线程:线程回收策略 线程间通信(互斥锁详解)
1. 线程回收策略
在 Linux 中,线程创建后,结束时需要被回收,否则会变成“僵尸线程”,占用系统资源。线程的回收方式主要有两种:
1.1 分离属性的线程
定义:不需要被其他线程回收的线程,称为分离属性的线程。
特点:线程退出后由 操作系统自动回收,不会变成僵尸线程。
设置方法:
#include <pthread.h>int pthread_detach(pthread_t thread);
示例:
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
pthread_detach(tid); // 设置为分离属性
1.2 非分离属性的线程(默认属性)
定义:可以被其他线程回收的线程(默认属性)。
特点:线程结束后不会立即释放资源,需要调用 pthread_join()
来回收。
使用方式:
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
pthread_join(tid, NULL); // 阻塞等待,回收线程资源
注意:
分离属性线程:不用 pthread_join()
,由系统自动回收。
非分离属性线程:需要 pthread_join()
,否则会变成僵尸线程。
2. 线程间通信
多线程之间需要共享数据时,最常见的方式是 全局变量通信。但是多个线程同时读写全局变量时,会导致 资源竞争问题。
2.1 临界资源
定义:多个线程可能同时访问的共享资源。
例子:全局变量、共享内存等。
2.2 互斥机制
为了解决资源竞争问题,通常使用 互斥锁(mutex) 来保证一次只有一个线程能访问临界资源。
使用步骤
创建互斥锁
pthread_mutex_t mutex;
初始化互斥锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
// 参数:
// mutex:互斥锁变量
// attr:互斥锁属性(一般填 NULL,使用默认属性)
// 返回值:成功 0,失败 -1
加锁
pthread_mutex_lock(&mutex);
解锁
pthread_mutex_unlock(&mutex);
销毁锁
pthread_mutex_destroy(&mutex);
2.3 示例代码
下面的例子中,两个线程同时对全局变量进行累加操作,使用互斥锁避免竞争:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>int counter = 0; // 全局变量(临界资源)
pthread_mutex_t mutex; // 定义互斥锁void *thread_func(void *arg) {for (int i = 0; i < 5; i++) {pthread_mutex_lock(&mutex); // 加锁counter++;printf("Thread %ld: counter = %d\n", pthread_self(), counter);pthread_mutex_unlock(&mutex); // 解锁sleep(1);}return NULL;
}int main() {pthread_t t1, t2;pthread_mutex_init(&mutex, NULL); // 初始化互斥锁pthread_create(&t1, NULL, thread_func, NULL);pthread_create(&t2, NULL, thread_func, NULL);pthread_join(t1, NULL); // 等待线程结束pthread_join(t2, NULL);pthread_mutex_destroy(&mutex); // 销毁锁return 0;
}
运行结果(不同系统输出可能不同,但一定是按序递增的,不会出现“抢占”):
Thread 140347929294592: counter = 1
Thread 140347920901888: counter = 2
Thread 140347929294592: counter = 3
Thread 140347920901888: counter = 4
...
总结
线程回收
分离属性:
pthread_detach()
,不需要pthread_join()
,由系统回收。非分离属性:默认,需要
pthread_join()
来回收,否则变僵尸线程。
线程间通信(互斥锁)
使用
pthread_mutex_t
来保护临界资源。加锁(
pthread_mutex_lock
)和解锁(pthread_mutex_unlock
)必须成对出现。最后记得
pthread_mutex_destroy()
。