志在指尖
用双手敲打未来

linux多线程(linux多线程编程实例)

linux多线程

提到线程,不得不让人想起进程,所以仍是先写下进程与线程的差异吧!
一、进程与线程的差异
进程是程序履行的一个实例,进程有其自己独立的地址空间。一个线程能够含有多个线程,这也是为了进步体系资源利用率,线程的引进有其必定的优势,线程有自己的堆栈。记得操作体系的书本上有一句经典的话:进程——资源分配的最小单位,线程——程序履行的最小单位。一个通俗的比喻:进程就像一个人,而线程就好像人体内和谐工作的各个组织部分,比如血液循环,人的呼吸,心脏的跳动,他们协同工作,共用人体(进程独立的资源空间)。
二、线程操作的基本函数
1、创立线程函数
#include
intpthread_create(pthread_t*restricttidp,
constpthread_attr_t*restrictattr,
void*(*start_rtn)(void),
void*restrictarg);
成功创立回来0,回来其他值犯错。
tidp:指向线程标识符的指针。
attr:设置线程特点。
start_trn:线程运转函数的起始地址。
arg:运转函数的参数。
2、线程特点函数
#include
intpthread_attr_init(pthread_attr_t*attr);//对线程特点进行初始化。
intpthread_attr_destroy(pthread_attr_t*attr);//去除线程的初始化特点。
若成功回来0,失利回来-1。
attr:线程特点变量。
调用pthread_attr_init()函数后,attr中所包括的便是体系支撑的线程一切特点的默认值。pthread_attr_destroy()去除attr中的特点。线程特点结构如下:
typedefstruct
{
intdetachstate;线程的别离状况
intschedpolicy;线程调度战略
structsched_paramschedparam;线程的调度参数
intinheritsched;线程的承继性
intscope;线程的效果域
size_tguardsize;线程栈结尾的戒备缓冲区巨细
intstackaddr_set;
void*stackaddr;线程栈的方位
size_tstacksize;线程栈的巨细
}pthread_attr_t;
(1)线程的别离状况
有一个函数能够对线程的别离状况进行操控。
#include
intpthread_attr_getdetachstate(constpthread_attr_t*attr,int*detachstate);//获取线程的别离状况
intpthread_attr_setdetachstate(pthread_attr_t*attr,intdetachstate);//设置线程的别离状况
若成功回来0,若失利回来-1。
attr:线程特点变量。
detachstate,intdetachstate:线程的别离状况特点。detachstate能够设置为PTHREAD_CREATE_DETACHED(别离状况发动线程),PTHREAD_CREATE_JOINABLE(正常发动线程)。
线程的别离状况决议一个线程以什么样的方法来停止自己。在默认情况下线程是非别离状况的,这种情况下,原有的线程等候创立的线程完毕。只有当pthread_join()函数回来时,创立的线程才算停止,才能开释自己占用的体系资源。
而别离线程不是这样子的,它没有被其他的线程所等候,自己运转完毕了,线程也就停止了,立刻开释体系资源。程序员应该依据自己的需求,选择恰当的别离状况。所以假如咱们在创立线程时就知道不需求了解线程的停止状况,则能够pthread_attr_t结构中的detachstate线程特点,让线程以别离状况发动。
(2)线程的承继
#include
intpthread_attr_getinheritsched(constpthread_attr_t*attr,int*inheritsched);//获取线程的承继性
intpthread_attr_setinheritsched(pthread_attr_t*attr,intinheritsched);//设置线程的承继性
若成功回来0,若失利回来-1。
attr:线程特点变量。
inheritsched:线程的承继性。
承继性决议调度的参数是从创立的进程中承继仍是使用在schedpolicy和schedparam特点中显式设置的调度信息。线程不为inheritsched指定默认值,因此假如你关心线程的调度战略和参数,必须先设置该特点。
承继性的可能值是PTHREAD_INHERIT_SCHED(表明新线程将承继创立线程的调度战略和参数)和PTHREAD_EXPLICIT_SCHED(表明使用在schedpolicy和schedparam特点中显式设置的调度战略和参数)。
假如需求显式的设置一个线程的调度战略或参数,那么就必须在设置之前将inheritsched特点设置PTHREAD_EXPLICIT_SCHED。
(3)线程的调度战略
#include
intpthread_attr_getschedpolicy(constpthread_attr_t*attr,int*policy);//获取线程的调度战略
intpthread_attr_setschedpolicy(pthread_attr_t*attr,intpolicy);//设置线程的调度战略
若成功回来0,若失利回来-1。
attr:线程特点变量指针。
policy:调度战略。其中有如下调度战略。
SCHED_FIFO(先进先出):允许一个线程运转直到有更高优先级的线程准备好,或许直到它自愿阻塞自己。在SCHED_FIFO调度战略下,当有一个线程准备好时,除非有相等或更高优先级的线程已经在运转,否则它会很快开端履行。
SCHED_RR(轮循):假如有一个SCHED_RR战略的线程履行了超越一个固定的时期(时间片距离)没有阻塞,而另外的SCHED_RR或SCHBD_FIFO战略的相同优先级的线程准备好时,运转的线程将被抢占以便准备好的线程能够履行。
当有SCHED_FIFO或SCHED_RR战略的线程在一个条件变量上等候或等候加锁同一个互斥量时,它们将以优先级顺序被唤醒。即,假如一个低优先级的SCHED_FIFO线程和一个高优先级的SCHED_FIFO线程都在等候锁相同的互斥量,则当互斥量被解锁时,高优先级线程将总是被首先解除阻塞。
(4)线程的调度参数
#include
intpthread_attr_getschedparam(constpthread_attr_t*attr,structsched_param*param);
//获取线程的调度参数
intpthread_attr_setschedparam(pthread_attr_t*attr,conststructsched_param*param);
//设置线程的调度参数
若成功回来0,若失利回来-1。
attr:线程特点变量指针。
param:sched_param结构。结构sched_param在文件/usr/include/bits/sched.h中界说如下:
structsched_param
{
intsched_priority;
};
结构sched_param的子成员sched_priority操控一个优先权值,大的优先权值对应高的优先权。体系支撑的最大和最小优先权值能够用sched_get_priority_max函数和sched_get_priority_min函数别离得到。
(3)等候其他线程退出函数
#include
intpthread_join(pthread_tthread,void**retval);
回来值:0代表成功。失利,回来的则是过错号。
thread:线程ID。
retval:用户界说的指针,用来存储被等候线程的回来值。
以阻塞的方法等候thread指定的线程完毕。当函数回来时,被等候线程的资源被回收。假如线程已经完毕,那么该函数会立即回来。并且thread指定的线程必须是joinable的。linux

linux多线程编程实例

1线程根本知识
进程是资源管理的根本单元,而线程是体系调度的根本单元,线程是操作体系能够进行调度运算的最小单位,它被包含在进程之中,是进程中的实践运作单位。一条线程指的是进程中一个单一顺序的操控流,一个进程中可以并发多个线程,每条线程并行履行不同的任务。
一个进程在某一个时间只能做一件事情,有了多个操控线程今后,在程序的规划成在某一个时间能够做不止一件事,每个线程处理单独的任务。
需求留意的是:即便程序运转在单核处理器上,也能够得到多线程编程模型的好处。处理器的数量并不影响程序结构,所以不管处理器个数多少,程序都可以通过线程得以简化。
linux操作体系运用契合POSIX线程作为体系规范线程,该POSIX线程规范界说了一整套操作线程的API。
2.线程标识
与进程有一个ID相同,每个线程有一个线程ID,所不同的是,进程ID在整个体系中是仅有的,而线程是依附于进程的,其线程ID只要在所属的进程中才有含义。线程ID用pthread_t表明。
//pthread_self直接回来调用线程的ID
include
pthread_tpthread_self(void);
判别两个线程ID的巨细是没有任何含义的,但有时或许需求判别两个给定的线程ID是否持平,运用以下接口:
1
2
3
//pthread_equal假如t1和t2所指定的线程ID相同,回来0;不然回来非0值。
include
intpthread_equal(pthread_tt1,pthread_tt2);
3.线程创立
一个线程的生命周期起始于它被创立的那一刻,创立线程的接口:
1
2
3
#include
intpthread_create(pthread_t*thread,constpthread_attr_t*attr,
void*(*start_routine)(void*),void*arg);
函数参数:
1
2
3
4
thread(输出参数),由pthread_create在线程创立成功后回来的线程句柄,该句柄在后续操作线程的API中用于标志该新建的线程;
start_routine(输入参数),新建线程的进口函数;
arg(输入参数),传递给新线程进口函数的参数;
attr(输入参数),指定新建线程的特点,如线程栈巨细等;假如值为NULL,表明运用体系默许特点。
函数回来值:
1
2
成功,回来0;
失利,回来相关错误码。
需求留意:
1.主线程,这是一个进程的初始线程,其进口函数为main函数。
2.新线程的运转机遇,一个线程被创立之后有或许不会被马上履行,乃至,在创立它的线程结束后还没被履行;也有或许新线程在当前线程从pthread_create前就已经在运转,乃至,在pthread_create前从当前线程回来前新线程就已经履行结束。
程序实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include
#include
#include
#include
voidprintids(constchar*s){
pid_tpid;
pthread_ttid;
pid=getpid();
tid=pthread_self();
printf(“%s,pid%lutid%lu(0x%lx)\n”,s,(unsignedlong)pid,(unsignedlong)tid,
(unsignedlong)tid);
}
void*thread_func(void*arg){
printids(“newthread:”);
return((void*)0);
}
intmain(){
interr;
pthread_ttid;
err=pthread_create(&tid,NULL,thread_func,NULL);
if(err!=0){
fprintf(stderr,”createthreadfail.\n”);
exit(-1);
}
printids(“mainthread:”);
sleep(1);
return0;
}
留意上述的程序中,主线程休眠一秒,假如不休眠,则主线程不休眠,则其或许会退出,这样新线程或许不会被运转,我自己注释掉sleep函数,发现好多次才能让新线程输出。
编译指令:
1
gcc-othreadthread.c-lpthread
运转成果如下:
mainthread:,pid889tid139846854309696(0x7f30a212f740)
newthread:,pid889tid139846845961984(0x7f30a1939700)
可以看到两个线程的进程ID是相同的。其共享进程中的资源。
4.线程停止
线程的停止分两种形式:被迫停止和自动停止
被迫停止有两种方法:
1.线程地点进程停止,恣意线程履行exit、_Exit或者_exit函数,都会导致进程停止,然后导致依附于该进程的一切线程停止。
2.其他线程调用pthread_cancel请求取消该线程。
自动停止也有两种方法:
1.在线程的进口函数中履行return句子,main函数(主线程进口函数)履行return句子会导致进程停止,然后导致依附于该进程的一切线程停止。
2.线程调用pthread_exit函数,main函数(主线程进口函数)调用pthread_exit函数,主线程停止,但假如该进程内还有其他线程存在,进程会持续存在,进程内其他线程持续运转。
线程停止函数:
include
voidpthread_exit(void*retval);
线程调用pthread_exit函数会导致该调用线程停止,并且回来由retval指定的内容。
留意:retval不能指向该线程的栈空间,不然或许成为野指针!

未经允许不得转载:IT技术网站 » linux多线程(linux多线程编程实例)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

志在指尖 用双手敲打未来

登录/注册IT技术大全

热门IT技术

C#基础入门   SQL server数据库   系统SEO学习教程   WordPress小技巧   WordPress插件   脚本与源码下载