一、线程的概念
线程是操作系统调度的最小单位,它是进程中的一个执行单位。一个进程可以拥有多个线程,这些线程可以共享进程的资源,包括内存、文件等。线程之间的切换比进程之间的切换代价要小很多,也更加高效。在Linux系统中,线程的实现依赖于操作系统提供的POSIX线程库(pthread)。
二、线程的创建和销毁
线程的创建和销毁是多线程编程的基本操作。在Linux系统中,线程的创建和销毁都是通过pthread库提供的函数实现的。例如,创建一个线程可以使用pthread_create函数,销毁一个线程可以使用pthread_cancel函数。
void *thread_func(void *arg){
printf("This is a pthread.\n");
pthread_exit(NULL);
}
int main(){
pthread_t tid;
int ret = pthread_create(&tid, NULL, thread_func, NULL); //创建一个线程
if(ret){
printf("Create pthread error!\n");
return -1;
}
pthread_join(tid, NULL); //等待子线程结束
return 0;
}
在上面的示例代码中,pthread_t类型的tid变量储存着新建线程的线程ID。pthread_create函数接受四个参数,第一个参数是指向新线程标识符的指针,第二个参数用于设置线程属性,第三个参数是新线程运行的函数,第四个参数是传给函数的参数。pthread_join函数用于等待子线程结束。
三、线程同步与互斥
线程同步与互斥是多线程编程中必须掌握的概念,它们是保证多个线程安全共享数据的重要手段。Linux系统提供了多种同步和互斥机制,其中最常用的是互斥锁和条件变量。
pthread_mutex_t mutex;
pthread_cond_t cond;
void *thread_func(void *arg){
// 模拟线程同步
pthread_mutex_lock(&mutex); // 加锁
pthread_cond_wait(&cond, &mutex); // 等待条件变量的信号
pthread_mutex_unlock(&mutex); // 解锁
printf("Thread is over.\n");
pthread_exit(NULL);
}
int main(){
pthread_t tid;
pthread_mutex_init(&mutex, NULL); // 初始化互斥锁
pthread_cond_init(&cond, NULL); // 初始化条件变量
int ret = pthread_create(&tid, NULL, thread_func, NULL); // 创建一个线程
if(ret){
printf("Create pthread error!\n");
return -1;
}
// 模拟线程同步
sleep(5);
pthread_cond_signal(&cond); // 发送信号
pthread_join(tid, NULL); // 等待子线程结束
pthread_mutex_destroy(&mutex); // 销毁互斥锁
pthread_cond_destroy(&cond); // 销毁条件变量
return 0;
}
在上面的示例代码中,使用pthread_mutex_t定义了互斥锁和pthread_cond_t定义了条件变量。pthread_mutex_lock和pthread_mutex_unlock函数用于加锁和解锁互斥锁,pthread_cond_wait函数用于等待条件变量的信号,pthread_cond_signal函数用于发送信号。
四、线程池
线程池是提高多线程执行效率的重要手段,它可以使得多个线程共享一定数量的线程资源,避免了线程频繁创建和销毁的开销。在Linux系统中,线程池的实现主要依赖于pthread库提供的线程创建、销毁和管理函数。
#define THREAD_NUM 5
#define QUEUE_SIZE 10
pthread_t threads[THREAD_NUM];
int queue[QUEUE_SIZE];
int front = 0, rear = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;
void *worker_func(void *arg){
int thread_id = *(int *)arg;
while(1){
pthread_mutex_lock(&mutex); // 加锁
while(front == rear){ // 队列为空,等待信号
pthread_cond_wait(&cond, &mutex);
}
int task = queue[front++]; // 从队列中取出任务
printf("Thread %d get task %d.\n", thread_id, task);
pthread_mutex_unlock(&mutex); // 解锁
sleep(2); // 模拟任务执行
}
pthread_exit(NULL);
}
int main(){
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
int tids[THREAD_NUM];
for(int i = 0; i < THREAD_NUM; i++){
tids[i] = i + 1;
pthread_create(&threads[i], NULL, worker_func, &tids[i]); // 创建线程
}
srand(time(NULL));
for(int i = 0; i < 20; i++){ // 向队列中添加任务
pthread_mutex_lock(&mutex); // 加锁
while((rear + 1) % QUEUE_SIZE == front){ // 队列已满,等待信号
pthread_cond_wait(&cond, &mutex);
}
queue[rear] = rand() % 100; // 添加任务
rear = (rear + 1) % QUEUE_SIZE;
printf("Task %d added to queue.\n", i);
pthread_mutex_unlock(&mutex); // 解锁
pthread_cond_signal(&cond); // 发送信号
sleep(1);
}
for(int i = 0; i < THREAD_NUM; i++){
pthread_cancel(threads[i]); // 结束线程
}
pthread_mutex_destroy(&mutex); // 销毁互斥锁
pthread_cond_destroy(&cond); // 销毁条件变量
return 0;
}
在上面的示例代码中,创建了一个固定大小的队列来储存任务,使用互斥锁保证队列的线程安全,使用条件变量通信。线程池中包括多个工作线程,它们都从队列中获取任务进行执行。主线程向队列中添加任务,使用pthread_cond_broadcast函数给所有线程发送信号,线程池的核心在于阻塞等待队列消息,并动态创建线程。
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/249916.html
微信扫一扫
支付宝扫一扫