浅谈并发服务器----多线程并发---1
来源:互联网 发布:linux alias ll 编辑:程序博客网 时间:2024/06/07 02:57
前面说来利用多进程来实现并发服务器,然而这种方法也并非没有缺点,在Linux系统中,当一个进程需要另一个实体执行某事时,该进程就使用fork派生一个新的子进程,让子进程去进行处理。在这种并发服务器中可以看到,父进程负责接收链接请求,建立连接,然后派生子进程,由子进程处理与客户的交互。
虽然这种方式很多年来都使用的很好,但使用fork生成子进程存在一些问题,首先,fork占用大量的资源,内存映像要从父进程拷贝到子进程,所有描述符都在子进程中复制等。虽然但前采用写时拷贝(Copy-on-Write)技术,将真正的拷贝推迟到子进程有写操作时,但fork仍然需要占大量资源,其次,fork子进程后,需要进程键通信(IPC)在父子进程间传递信息。由于子进程从一开始就有父进程数据空间及所有的描述符的拷贝,所以fork之前的信息容易传递,但是从子进程返回信息给父进程就需要做很多工作。
而采用多线程来实现,有助于解决上面两个问题。
一,线程基础
线程是进程内的独立执行实体和调度单元,又称为”轻量级”进程(Lightwight Process),创建线程比进程快10~100倍。一个进程内的所有线程共享相同的内存空间,全局变量等信息(这种机制又带来了同步问题),所以一个线程崩溃时,它会影响同一进程中的其他线程。除了共享全局变量外,他们还共享一下信息:进程治理,大多数数据,打开的文件描述符字,信号处理程序和信号处置,当前工作目录,用户ID和 组ID。
但每个线程都有自己的私有信息:线程ID,寄存器集合(包括程序计数器和栈指针),栈(用于存放局部变量),error,信号掩码,优先级。
二,线程基础函数
#include<pthread.h>
Int Pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*func(void *)), void *arg);
如果新线程创建成功,参数tid返回新生成线程ID,一个进程中的每个线程都由一个线程ID标识,其类型为pthread_t。Attr指向线程属性的指针每个线程有很多属性名,包括优先级,起始栈大小,是否是守护线程等。通常将attr参数的值设为NULL,这时使用系统默认的属性。
创建完一个新的线程后,需要说明它执行的函数。函数的地址由参数func指定。Func是一个函数指针,指向线程创建后要掉用的函数,这个被线程调用的函数也称为线程函数,该线程函数的调用参数是由arg指定的,arg是一个通用指针,用于往func()函数中传递参数,如果要传递多个参数时,必须将他们打包成一个结构,然后让arg指向该结构。
如果线程调用成功返回0,出错则返回非0.
Pthread_create()函数的用法如下:thread.c
//线程的创建函数//程序名:createthread.c//编程时间:2012.7.21#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<pthread.h>//线程函数void *thread(void *arg){pthread_tnewthid;newthid = pthread_self();printf("this is a new thread, thread ID = %lu\n", newthid);return NULL;}int main(void){pthread_tthid;printf("main thread , ID is %lu\n",pthread_self());//打印主线程的IDif(pthread_create(&thid, NULL, (void *)thread, NULL) != 0) {printf("thread ceatiion filed\n");exit(1);}sleep(1);exit(0);}linux下线程程序在编译时需要注意,gcc thread.c -o thread -pthread 注意到没在用gcc编译时要在后面加-pthread,这是链接线程静态库.
线程中也有和进程的waitpid()函数功能类似的函数,等待一个线程终止,pthread_join()函数如下:
#include<pthread,h>
int pthread_join(pthread_t tid, void **status);
参数tid指定要等待的ID。该函数必须指定尧等待的线程,不能等待任一个线程结束。要求等待的线程必须是等待进程的成员,并且不是分离的线程或守护线程。
几个线程不能同时等待一个线程完成(及多个线程调用pthread_join(),其指定同一个tid),如果其中一个成功调用pthread_join()函数,则其他线程将返回ESRCH
错误。如果等待的线程已经终止,则该函数立即返回。如果参数status指针非空,则指向终止线程的退出状态值。需要注意的是被等待的线程应该处于可join状态,
即非DETACHED状态。DETAVHED 状态是指对某个线程执行pthread_detach()后其所处的状态。处于DETACHED状态的线程无法由pthread_join()同步。
在线程创建函数pthread_create有一个参数pthread_attr_t ,该类型是一个结构体类型。结构体如下:
typedef struct{ int detachstate; int schedpolicy; struct sched_param schedpolicy; int inheritsched; int scope; size_t guardsize; int stackaddr_set; void * stackaddr; size_t stacksize;}pthread_attr_t;
各子段含义如下:(缺省<------->默认)
1. detachstate: 表示新创键的线程是否与进程中其他的线程脱离同步。detachstate的缺省值为PATHREAD_CREATE_JOINABLE状态,这个属性也可以个用
函数pthread_detach()来设置。如果将detachstate设置为PAHREAD_CREATE_DETACH(分离)状态,则detachstate不能载恢复到PATHREAD_CREATE_JOINABLE状态。(线程同步与异步的具体解释度娘或谷哥都行)
2. schedpolicy: 表示新线程的调度策略,主要包括SCHED_OTHER(正常,非实时),SCHED_RR(实时,轮转法)和 SCHED_FIFO(实时,先进先出)3种,缺省为SCHED_OTHER,后两种调度算法仅对超级用户有用。
3 . schedparam: 一个struct sched_param结构,其中一个sched_priority整型变量表示线程的运行优先级。这个参数仅当调度策略为实时(即SCHED_RR或SCHED_ FIFO)时才有效,缺省为0.
4. inheritsched: 有两种值可以选择,PTHEREAD_ECPLICIT_SCHED和PATHREAD_INHERIT_SCHED,前者表示新线程显示指定调度策略和调度参数(即attr中的值),而后者表示集成调用者线程的值。缺省为PTHREAD_EXPLICIT_SCHED.
5. scope: 表示进程间竞争CPU的范围,也就是说,线程优先级的有效范围。POSIX的标准中定义了两个值,PTHREAD_SCOPE_SYSTEM和PTHREAD_ SCOPE_PROCESS,前者biloxi系统中所有线程一起竞争CPU,后者表示仅与同进程的线程竞争CPU.
6.guardsize: 警戒堆栈的大小。
7.stackaddr_set: 堆栈地址集。
8.stackaddr: 堆栈的地址。
9.stacksize: 堆栈大小。
具体使用可在《Linux编程实战》中找到。。。。
pthread_detach()函数将指定的线程变成分离的。
pthread_detach()函数如下:
#include<pthread.h>
int pthread_detach(pthread_t tid);
参数tid指定要设置为分离的线程ID。如果函数调用成功返回0,否则返回错误码。
函数pthread_exit()用于终止当前线程,并返回状态值。如果当前线程是可联合的,则其退出状态将保留。
pthread_exit()函数如下:
#include<pthread.h>
void pthread_exit(void *status);
参数status指向函数的退出状态,这里的status不能指向一个局部变量,因为当前线程终止后其他所有的局部变量将
被撤销。该函数没有返回值。
还有两种方法可以使线程终止:
(1)启动线程的函数ptread_create()的第3个参数返回。该返回值就是线程的终止状态。
(2)如果进程的main()函数返回或者任何线程调用了exit()函数,进程将终止,线程将随之终止。
- 浅谈并发服务器----多线程并发---1
- 浅谈并发服务器----多线程并发----2
- 浅谈并发服务器---多线程并发----3
- 浅谈并发服务器---多线程并发---4(线程安全)
- 多线程并发服务器编程
- 多线程并发服务器编程
- 多线程并发服务器编程
- tcp多线程并发服务器
- 多线程并发服务器
- 多线程并发服务器
- 浅谈并发服务器---多进程并发---2
- 浅谈并发服务器---多进程并发---3
- 浅谈RxJava与多线程并发
- 多线程与并发服务器设计(23-1)
- 多线程与并发服务器设计(23-1)
- 多线程高并发服务器相关
- linux(二)------多线程并发服务器
- socket 并发服务器 多线程模式
- 升级金士顿固态硬盘SV200S3固件,还原其应有的速度
- Java 内存分配全面浅析
- LeetCode2.2.3 @ Partition List 链表划分 D3F3
- LUA技巧集合
- Why Hadoop2
- 浅谈并发服务器----多线程并发---1
- 【足迹C++primer】47、Moving Objects(2)
- Java常见错误列表
- Win7 C# 控制台程序写注册表被拒,需要以管理员身份运行。
- Codeforces Round #256 (Div. 2) | 前4题
- 2014年开发者需要了解的10大开发趋势和技能
- WinForm中,实现TextBox的验证
- Log4Net使用指南
- Actioncontext和ServletActioncontext的区别