1. 引言
多线程编程是Linux操作系统中非常重要的一部分,能够充分利用多核处理器的性能,提高程序的并发能力和响应速度。本文将介绍Linux多线程编程的实战指南,探讨如何编写高效、稳定的多线程程序。
2. 线程创建与销毁
2.1 线程创建
在Linux下创建线程主要使用pthread库函数,如下:
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
pthread_create()函数用于创建一个新线程,参数thread是指向线程ID的指针,attr是线程属性,start_routine是线程函数,arg是传递给线程函数的参数。
以下是一个简单的线程创建的示例:
#include <stdio.h>
#include <pthread.h>
void *thread_func(void *arg) {
int value = *(int *)arg;
printf("Received value: %d\n", value);
return NULL;
}
int main() {
pthread_t tid;
int arg_value = 10;
pthread_create(&tid, NULL, thread_func, &arg_value);
pthread_join(tid, NULL);
return 0;
}
在上面的示例中,main函数创建了一个新线程,并将参数10传递给线程函数thread_func。线程函数将接收到的参数打印出来,然后返回。
2.2 线程销毁
线程的销毁使用pthread库函数pthread_join,如下:
int pthread_join(pthread_t thread, void **retval);
pthread_join()函数用于等待指定线程的结束,并且获取线程的返回值。参数thread是要等待的线程ID,retval用于获取线程的返回值。
以下是一个简单的线程销毁的示例:
#include <stdio.h>
#include <pthread.h>
void *thread_func(void *arg) {
printf("Child thread running\n");
return NULL;
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
printf("Main thread waiting for child thread to exit\n");
pthread_join(tid, NULL);
printf("Child thread has exited\n");
return 0;
}
在上面的示例中,main函数创建了一个新线程,并等待新线程结束。等待结束后,打印出"Child thread has exited"。
3. 线程同步与互斥
3.1 互斥锁
互斥锁是一种常用的线程同步机制,用于保护共享资源,防止多个线程同时修改造成数据不一致的情况。在Linux下使用pthread库的互斥锁,如下:
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
使用pthread_mutex_lock()函数可以锁住互斥锁,保护共享资源,阻止其他线程访问。使用pthread_mutex_unlock()函数可以释放互斥锁,允许其他线程访问共享资源。
以下是一个简单的使用互斥锁的示例:
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int shared_value = 0;
void *thread_func(void *arg) {
pthread_mutex_lock(&mutex);
shared_value++;
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, thread_func, NULL);
pthread_create(&tid2, NULL, thread_func, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("Shared value: %d\n", shared_value);
return 0;
}
在上面的示例中,main函数创建两个并发线程,它们同时对shared_value变量进行递增操作。通过互斥锁保护共享资源,确保线程安全。
3.2 条件变量
条件变量是一种线程同步的工具,用于线程之间的通信和协调。在Linux下使用pthread库的条件变量,如下:
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
使用pthread_cond_wait()函数使线程等待某个条件变量满足,pthread_cond_signal()函数用于唤醒等待在条件变量上的线程,pthread_cond_broadcast()函数用于唤醒所有等待在条件变量上的线程。
以下是一个简单的使用条件变量的示例:
#include <stdio.h>
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int condition = 0;
void *thread_func(void *arg) {
pthread_mutex_lock(&mutex);
while (condition == 0) {
pthread_cond_wait(&cond, &mutex);
}
printf("Condition satisfied\n");
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
pthread_mutex_lock(&mutex);
condition = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
pthread_join(tid, NULL);
return 0;
}
在上面的示例中,main函数创建一个等待条件满足的线程。线程函数中使用pthread_cond_wait()函数等待条件变量满足。main函数在改变条件变量的值并调用pthread_cond_signal()函数唤醒等待线程后,打印出"Condition satisfied"。
4. 线程池
4.1 线程池的设计
线程池是一种管理多线程的机制,用于优化线程的创建和销毁的开销,提高线程的复用性。一个线程池通常包含一个任务队列和线程池管理器。
任务队列用于存放多个任务,每个任务包含一个线程函数和对应的参数。当需要执行任务时,线程池管理器从任务队列中取出一个任务,创建一个新线程来执行任务。
以下是一个简单的线程池的设计:
#include <stdio.h>
#include <pthread.h>
#define MAX_THREADS 10
#define MAX_TASKS 100
pthread_t threads[MAX_THREADS];
int task_count = 0;
typedef struct {
void *(*start_routine) (void *);
void *arg;
} task_t;
task_t task_queue[MAX_TASKS];
void *thread_func(void *arg) {
task_t *task;
while (1) {
pthread_mutex_lock(&mutex);
while (task_count == 0) {
pthread_cond_wait(&cond, &mutex);
}
task = &task_queue[task_count - 1];
task_count--;
pthread_mutex_unlock(&mutex);
task->start_routine(task->arg);
free(task);
}
return NULL;
}
void pool_init() {
int i;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
for (i = 0; i < MAX_THREADS; i++) {
pthread_create(&threads[i], NULL, thread_func, NULL);
}
}
void pool_submit(void *(*start_routine) (void *), void *arg) {
task_t *task = malloc(sizeof(task_t));
task->start_routine = start_routine;
task->arg = arg;
pthread_mutex_lock(&mutex);
task_queue[task_count] = *task;
task_count++;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void pool_destroy() {
int i;
for (i = 0; i < MAX_THREADS; i++) {
pthread_join(threads[i], NULL);
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
}
在上面的示例中,创建一个具有10个线程的线程池,线程池的任务队列容量为100。pool_init()函数用于初始化线程池,pool_submit()函数用于提交任务给线程池,pool_destroy()函数用于销毁线程池。
5. 总结
本文介绍了Linux多线程编程的实战指南,包括线程的创建与销毁、线程同步与互斥、线程池的设计等内容。了解并掌握多线程编程是提升程序并发性和响应速度的关键。希望本文对读者有所帮助。