Linux多线程编程实战指南

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多线程编程的实战指南,包括线程的创建与销毁、线程同步与互斥、线程池的设计等内容。了解并掌握多线程编程是提升程序并发性和响应速度的关键。希望本文对读者有所帮助。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。

操作系统标签