
C语言是一种非常流行的编程语言,被广泛应用于各种应用程序和系统开发。C语言支持多线程编程,多线程是同时执行的多个独立的线程,可以提高程序性能和并发处理能力。本文将介绍C语言多线程编程的基本概念、使用方法和实例说明。
一、多线程编程基本概念
1.线程概念
线程是操作系统调度的基本单位,是进程中的一个控制流程,说白了就是程序执行的一条路径。一个程序可以包含多个线程,它们可以同时或交替执行,共享相同的全局数据。
2.线程的优点
(1)提高程序并发处理能力,充分利用多核CPU的计算资源。
(2)增加程序的响应速度,提高用户体验。
(3)避免单线程程序的阻塞,提高程序的稳定性和可靠性。
(4)可以将复杂的任务拆分成多个小任务,并行执行,提高程序的执行效率。
3.线程创建和销毁
线程的创建和销毁是多线程编程的重要操作,可以通过函数pthread_create()和pthread_exit()实现。
pthread_create()函数的原型如下:
```c
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
```
参数说明:
- thread:指向新线程的指针。
- attr:指向线程属性结构体的指针,可以为NULL。
- start_routine:是新线程执行的函数,返回void *类型的指针,参数为void *类型的指针。
- arg:是传递给新线程的参数,可以为NULL。
pthread_exit()函数的原型如下:
```c
void pthread_exit(void *retval);
```
参数说明:
- retval:指定的线程退出状态。
二、多线程编程使用方法
1.头文件和链接库
多线程编程需要包含头文件pthread.h,并链接pthread库,可以使用编译选项"-pthread"或"-lpthread"来指定。
2.线程创建
在主线程中,通过调用pthread_create()函数创建新线程并执行指定的线程函数。
```c
#include  void *thread_func(void *arg)//线程函数 {     //do something      pthread_exit((void *) 0); } int main() {     pthread_t tid; //线程ID     int ret; //返回值     ret = pthread_create(&tid, NULL, thread_func, NULL);//创建新线程     if (ret != 0) {         printf("pthread_create error.\n");         return -1;     }     //do something     pthread_exit((void *) 0); //主线程退出     return 0; } ``` 3.线程等待 在主线程中,可以通过调用pthread_join()函数等待子线程完成。 ```c #include  void *thread_func(void *arg) {     //do something      pthread_exit((void *) 0); } int main() {     pthread_t tid; //线程ID     int ret; //返回值     ret = pthread_create(&tid, NULL, thread_func, NULL);//创建新线程     if (ret != 0) {         printf("pthread_create error.\n");         return -1;     }     //等待子线程完成     ret = pthread_join(tid, NULL);     if (ret != 0) {         printf("pthread_join error.\n");         return -1;     }     //do something     pthread_exit((void *) 0); //主线程退出     return 0; } ``` 4.线程同步 多个线程同时访问同一个全局变量可能会出现数据竞争问题,需要使用线程同步技术来解决。 - 互斥锁 互斥锁用于对共享资源的互斥访问,通过pthread_mutex_init()函数初始化互斥锁,pthread_mutex_lock()函数加锁,pthread_mutex_unlock()函数解锁。 ```c #include  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //定义静态初始化互斥锁 void *thread_func(void *arg) {     //加锁     pthread_mutex_lock(&mutex);     //do something      //解锁     pthread_mutex_unlock(&mutex);     pthread_exit((void *) 0); } int main() {     pthread_t tid; //线程ID     int ret; //返回值     ret = pthread_create(&tid, NULL, thread_func, NULL);//创建新线程     if (ret != 0) {         printf("pthread_create error.\n");         return -1;     }     pthread_mutex_lock(&mutex);//加锁     //do something     pthread_mutex_unlock(&mutex);//解锁     pthread_exit((void *) 0); //主线程退出     return 0; } ``` - 条件变量 条件变量用于线程间的事件通知和等待,通过pthread_cond_init()函数初始化条件变量,pthread_cond_wait()函数等待条件变量,pthread_cond_signal()或pthread_cond_broadcast()函数唤醒等待线程。 ```c #include  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //定义静态初始化互斥锁 pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //定义静态初始化条件变量 void *thread_func(void *arg) {     pthread_mutex_lock(&mutex);//加锁     //等待条件变量     ret = pthread_cond_wait(&cond, &mutex);     if (ret != 0) {         printf("pthread_cond_wait error.\n");         return -1;     }     //do something      pthread_mutex_unlock(&mutex);//解锁     pthread_exit((void *) 0); } int main() {     pthread_t tid; //线程ID     int ret; //返回值     ret = pthread_create(&tid, NULL, thread_func, NULL);//创建新线程     if (ret != 0) {         printf("pthread_create error.\n");         return -1;     }     pthread_mutex_lock(&mutex);//加锁     //设置条件变量     ret = pthread_cond_signal(&cond);     if (ret != 0) {         printf("pthread_cond_signal error.\n");         return -1;     }     pthread_mutex_unlock(&mutex);//解锁     pthread_exit((void *) 0); //主线程退出     return 0; } ``` 5.线程池 线程池是一种常见的多线程编程模型,可以提高程序执行效率和并发处理能力。 ```c #include  #include  #define MAX_THREADS 10 //最大线程数  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //定义静态初始化互斥锁 pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //定义静态初始化条件变量 int thread_count = 0; //线程数计数器 bool thread_func(void *arg) {     //do something      return true; } void *thread_pool_func(void *arg) {     while (true) {         pthread_mutex_lock(&mutex);//加锁         while (thread_count == 0) {             pthread_cond_wait(&cond, &mutex);//等待条件变量         }         thread_count--;         pthread_mutex_unlock(&mutex);//解锁         thread_func(arg);//线程函数     } } int main() {     pthread_t tid[MAX_THREADS]; //线程ID数组     int i; //循环计数器     int ret; //返回值     for (i = 0; i < MAX_THREADS; i++) {         ret = pthread_create(&tid[i], NULL, thread_pool_func, NULL);//创建新线程         if (ret != 0) {             printf("pthread_create error.\n");             return -1;         }     }     //do something     pthread_mutex_lock(&mutex);//加锁     thread_count++;     pthread_cond_signal(&cond);//唤醒等待线程     pthread_mutex_unlock(&mutex);//解锁     return 0; } ``` 三、多线程编程实例说明 1.多线程并发服务器 ```c #include  #include  #include  #include  #include  #include  #define MAX_CLIENTS 10 //最大客户数  #define BUF_SIZE 1024 //缓冲区大小 int client_count = 0; //客户数计数器 int client_fds[MAX_CLIENTS]; //客户套接字数组 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //定义静态初始化互斥锁 void *client_func(void *arg) {     int sockfd = *(int *)arg; //客户套接字     char buf[BUF_SIZE]; //缓冲区     int n;     while (true) {         n = read(sockfd, buf, BUF_SIZE);//读取客户数据         if (n <= 0) {             //客户已断开连接             pthread_mutex_lock(&mutex);//加锁             for (int i = 0; i < client_count; i++) {                 if (client_fds[i] == sockfd) {                     client_count--;                     for (int j = i; j < client_count; j++) {                         client_fds[j] = client_fds[j+1];                     }                     break;                 }             }             pthread_mutex_unlock(&mutex);//解锁             close(sockfd);//关闭客户套接字             return NULL;         }         buf[n] = '\0';         printf("[Client %d]: %s", sockfd, buf);//在服务器打印出客户数据         //将数据广播给其他客户         pthread_mutex_lock(&mutex);//加锁         for (int i = 0; i < client_count; i++) {             if (client_fds[i] != sockfd) {                 write(client_fds[i], buf, n);             }         }         pthread_mutex_unlock(&mutex);//解锁         memset(buf, 0, BUF_SIZE);     } } void *server_func(void *arg) {     int sockfd = *(int *)arg; //服务器套接字     int connfd; //客户套接字     struct sockaddr_in client_addr; //客户地址     socklen_t client_len = sizeof(client_addr);     while (true) {         connfd = accept(sockfd, (struct sockaddr *) &client_addr, &client_len);//等待客户连接         if (connfd < 0) {             printf("accept error\n");             continue;         }         pthread_mutex_lock(&mutex);//加锁         if (client_count < MAX_CLIENTS) {             client_fds[client_count] = connfd;             client_count++;             pthread_t tid;             pthread_create(&tid, NULL, client_func, &connfd);//为客户创建新线程             printf("[Server]: Client %s:%d connected.\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));//在服务器打印客户连接信息         } else {             printf("too many clients\n");             close(connfd);//关闭客户套接字         }         pthread_mutex_unlock(&mutex);//解锁     } } int main(int argc, char *argv[]) {     int sockfd; //服务器套接字     struct sockaddr_in server_addr; //服务器地址     pthread_t tid;          //创建服务器套接字     sockfd = socket(AF_INET, SOCK_STREAM, 0);     if (sockfd < 0) {         printf("socket error\n");         return -1;     }          //绑定服务器地址     bzero(&server_addr, sizeof(server_addr));     server_addr.sin_family = AF_INET;     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);     server_addr.sin_port = htons(8888);     if (bind(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {         printf("bind error\n");         return -1;     }          //监听客户连接     if (listen(sockfd, 10) < 0) {         printf("listen error\n");         return -1;     }          //创建服务器线程     pthread_create(&tid, NULL, server_func, &sockfd);          //等待线程结束     pthread_join(tid, NULL);          //关闭套接字     close(sockfd);          return 0; } ``` 2.多线程图像处理 这个例子演示了如何使用多线程来加速图像处理,代码实现了双边滤波算法,可以处理RGB图像。 ```c #include  #include  #include  #include  #include  #include "bmpfile.h" #define MAX_THREADS 10 //最大线程数  bmpfile_t *read_bmp(const char *filename); int write_bmp(bmpfile_t *bmp, const char *filename); void *thread_func(void *arg); struct thread_data{     int start;     int end;     bmpfile_t *bmp_in;     bmpfile_t *bmp_out; }; int main(int argc, char* argv[]) {     bmpfile_t *bmp_in, *bmp_out;     uint32_t width, height;     int threads, i, ret;     pthread_t tid[MAX_THREADS];     struct thread_data td[MAX_THREADS];     if (argc != 4) {         printf("Usage: bilateral_filter input.bmp output.bmp threads\n");         return -1;     }     bmp_in = read_bmp(argv[1]);//读取输入图像     if (bmp_in == NULL) {         printf("read bmp error\n");         return -1;     }     if (bmp_in->header.bitcount != 24) {         printf("only support 24-bit image\n");         bmp_destroy(bmp_in);         return -1;     }     width = bmp_in->header.width;     height = bmp_in->header.height;     bmp_out = bmp_create(width, height, bmp_in->header.bitcount);//创建输出图像     if (bmp_out == NULL) {         printf("bmp create error\n");         bmp_destroy(bmp_in);         return -1;     }     threads = atoi(argv[3]);//获取线程数     if (threads <= 0 || threads > MAX_THREADS) {         threads = 1;     }     for (i = 0; i < threads; i++) {         td[i].start = (i * height) / threads;         td[i].end = ((i + 1) * height) / threads - 1;         td[i].bmp_in = bmp_in;         td[i].bmp_out = bmp_out;         ret = pthread_create(&tid[i], NULL, thread_func, &td[i]);//为每个线程创建任务         if (ret != 0) {             printf("pthread_create error.\n");         }     }     for (i = 0; i < threads; i++) {         pthread_join(tid[i], NULL);//等待所有线程完成任务     }     write_bmp(bmp_out, argv[2]);//保存输出图像     bmp_destroy(bmp_in);     bmp_destroy(bmp_out);     return 0; } bmpfile_t *read_bmp(const char *filename) {     bmpfile_t *bmp = NULL;     FILE *f = fopen(filename, "rb");     if (f != NULL) {         bmp = bmp_create_32(0,0,0);         bmp_read(bmp, f);         fclose(f);     }     return bmp; } int write_bmp(bmpfile_t *bmp, const char *filename) {     if (bmp == NULL || filename == NULL) {         return -1;     }     FILE *f = fopen(filename, "wb");     if (f != NULL) {         bmp_write(bmp, f);         fclose(f);         return 0;     }     return -1; } void *thread_func(void *arg) {     int x, y, i, j, k, r, g, b;     double w, dw, weight, dist, r_sum, g_sum, b_sum, weight_sum;     bmpfile_t *bmp_in, *bmp_out;     struct thread_data *td = (struct thread_data *)arg;     uint32_t width = td->bmp_in->header.width;     uint32_t height = td->end - td->start + 1;     uint8_t *p_in = td->bmp_in->data + td->start * td->bmp_in->header.pitch;     uint8_t *p_out = td->bmp_out->data + td->start * td->bmp_out->header.pitch;     for (y = td->start; y <= td->end; y++) {         for (x = 0; x < width; x++) {             r_sum = 0.0; g_sum = 0.0; b_sum = 0.0; weight_sum = 0.0;//初始化             for (i = -2; i <= 2; i++) {                 for (j = -2; j <= 2; j++) {                     if (y + i >= 0 && y + i < height && x + j >= 0 && x + j < width) {                         r = p_in[(y                            如果你喜欢我们三七知识分享网站的文章,
欢迎您分享或收藏知识分享网站文章
欢迎您到我们的网站逛逛喔!https://www.ynyuzhu.com/
                        
 
                 
                ![最新版TikTok 抖音国际版解锁版 v33.8.4 去广告 免拔卡[免费网盘]](https://m.ynyuzhu.com/uploads/20240316/368374f292fe1b61eead785c71e11147.jpg) 
                
走该走的路,见想见的人。