修改服务器为多线程模式

本文介绍了多线程的基本概念,包括线程的定义、主线程和子线程的区别,以及如何使用pthread_create函数创建子线程。文中通过示例展示了线程的创建过程,并探讨了多线程在提高响应速度、利用多核CPU和处理共享数据等方面的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、多线程简介
1、什么是线程?
       线程在操作系统原理中是这样描述的:线程是进程的一条执行路径。线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,所有的线程都是在同一进程空间运行,这也意味着多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。 一个进程可以有很多线程,每条线程并行执行不同的任务。

2、主线程和子线程
       一个进程创建后,会首先生成一个缺省的线程,通常称这个线程为主线程(或称控制线程),C/C++程序中,主线程就是通过main函数进入的线程,由主线程调用pthread_create()创建的线程称为子线程,子线程也可以有自己的入口函数,该函数由用户在创建的时候指定。每个线程都有自己的线程ID,可以通过pthread_self()函数获取。最常见的线程模型中,除主线程较为特殊之外,其他线程一旦被创建,相互之间就是对等关系,不存在隐含的层次关系。每个进程可创建的最大线程数由具体实现决定。

       无论在windows中还是Posix中,主线程和子线程的默认关系是:无论子线程执行完毕与否,一旦主线程执行完毕退出,所有子线程执行都会终止。这时整个进程结束或僵死,部分线程保持一种终止执行但还未销毁的状态,而进程必须在其所有线程销毁后销毁,这时进程处于僵死状态。线程函数执行完毕退出,或以其他非常方式终止,线程进入终止态,但是为线程分配的系统资源不一定释放,可能在系统重启之前,一直都不能释放,终止态的线程,仍旧作为一个线程实体存在于操作系统中,什么时候销毁,取决于线程属性。在这种情况下,主线程和子线程通常定义以下两种关系:

可会合(joinable):这种关系下,主线程需要明确执行等待操作,在子线程结束后,主线程的等待操作执行完毕,子线程和主线程会合,这时主线程继续执行等待操作之后的下一步操作。主线程必须会合可会合的子线程。在主线程的线程函数内部调用子线程对象的wait函数实现,即使子线程能够在主线程之前执行完毕,进入终止态,也必须执行会合操作,否则,系统永远不会主动销毁线程,分配给该线程的系统资源也永远不会释放。
相分离(detached):表示子线程无需和主线程会合,也就是相分离的,这种情况下,子线程一旦进入终止状态,这种方式常用在线程数较多的情况下,有时让主线程逐个等待子线程结束,或者让主线程安排每个子线程结束的等待顺序,是很困难或不可能的,所以在并发子线程较多的情况下,这种方式也会经常使用。
       线程的分离状态决定一个线程以什么样的方式来终止自己,在默认的情况下,线程是非分离状态的,这种情况下,原有的线程等待创建的线程结束,只有当pthread_join函数返回时,创建的线程才算终止,释放自己占用的系统资源,而分离线程没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。

3、创建子线程
pthread_create()函数

函数原型:

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void
*arg);

下面以一个程序演示子线程的创建
代码如下:

1  #include <stdio.h>
2  #include <string.h>
3  #include <errno.h>
4  #include <stdlib.h>
5  #include <unistd.h>
6  #include <pthread.h>
7
8  void *thread_worker1(void *args);
9  void *thread_worker2(void *args);
10
11 int main(int argc, char *argv[])
12 {
13      int                 shared_var = 1000;
14        pthread_t             tid;
15         pthread_attr_t         thread_attr;
16
17
18         if (pthread_attr_init(&thread_attr))
19        {
20             printf("pthread_attr_init() failure: %s\n", strerror(errno));
21             return -1;
22        }
23
24         if (pthread_attr_setstacksize(&thread_attr, 120*1024))    //重新设置子线程栈大小
25         {
26             printf("pthread_attr_setstacksize() failure: %s\n", strerror(errno));
27             return -1;
28        }
29        //设置子线程与主线程为相分离的关系
30        if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
31         {
32             printf("pthread_attr_setdetachstate() failure: %s\n", strerror(errno));
33             return -1;
34         }
35        //创建第一个子线程,去执行thread_worker1()
36         pthread_create(&tid, &thread_attr, thread_worker1, &shared_var);
37         printf("Thread worker1 tid[%ld] created ok\n", tid);
38        //创建第二个子线程,去执行thread_worker2()
39        pthread_create(&tid, NULL, thread_worker2, &shared_var);
40         printf("Thread worker2 tid[%ld] created ok\n", tid);
41
42         pthread_attr_destroy(&thread_attr);        //销毁为线程重新设置的属性
43
44         /* 第二个子线程默认是joinable,在这里阻塞,等待与子线程会合 */
45         pthread_join(tid, NULL);
46
47
48         while (1)
49         {
50             printf("Main/Control thread shared_var: %d\n", shared_var);
51             sleep(10);
52         }
53 }
54 
55 void *thread_worker1(void *args)
56 {
57         int *ptr = (int *)args;
58
59         if (!args)
60         {
61             printf("%s() get invalid arguments\n", __FUNCTION__);
62             pthread_exit(NULL);
63        }
64
65         printf("Thread workder 1 [%ld] start running...\n", pthread_self());
66
67         while (1)
68         {
69             printf("+++: %s before shared_var++: %d\n", __FUNCTION__, *ptr);
70             *ptr += 1;
71             sleep(2);
72             printf("+++: %s after sleep shared_var: %d\n", __FUNCTION__, *ptr);
73         }
74
75         printf("Thread workder 1 exit...\n");
76
77         return NULL;
78 }
79 //宏__FUNCTION__用来获取函数名
80 void *thread_worker2(void *args)
81 {
82         int *ptr = (int *)args;
83
84         if (!args)
85         {
86             printf("%s() get invalid arguments\n", __FUNCTION__);
87             pthread_exit(NULL);
88         }
89
90         printf("Thread workder 2 [%ld] start running...\n", pthread_self());
91
92         while (1)
93         {
94             printf("---: %s before shared_var++: %d\n", __FUNCTION__, *ptr);
95             *ptr += 1;
96             sleep(2);
97             printf("---: %s after sleep shared_var: %d\n", __FUNCTION__, *ptr);
98         }
99
100     printf("Thread workder 2 exit...\n");
101
102     return NULL;
103 }

4.适用于多线程的场景
提高响应速度,让IO和计算相互重叠,降低时延。
1.有多个cpu可用。
2.线程间有共享数据。
3.共享数据可以修改
4.提供非均质服务。处理事务有优先级之分,防止出现优先级反转。
5.利用异步操作。
6.能scale up。
7.具有可预测的性能。
8.能够有效的划分责任与功能,让每个线程逻辑比较简单。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值