linux下多线程编程

来源:互联网 发布:斗鱼登录网络异常 编辑:程序博客网 时间:2024/05/20 04:32

本文整理自(http://blog.csdn.net/jiajun2001/article/details/12624923)

多线程

1.头文件

#include<pthread.h>

2.函数说明

2.1  pthread_create()

Int pthread_create(pthread_t *thread, pthread_attr_t *attr,void *(*start_routine)(void *), void *arg)

Using

Parm

Ret

Others

创建一个线程

1.  thread

输出:创建线程句柄

2.  attr

输入:设置线程属性,一般设置为NULL。见附录

3.  start_routine

输入:线程处理函数

4.  arg

输入:线程处理函数的参数

0:成功

 

2.2  pthread_join()

Int pthread_join(pthread_t th,void **thread_return)

Using

Parm

Ret

Others

线程同步:等待一个线程结束执行本线程。

1.  th

输入:要等待结束的线程句柄,pthread_create()

的第一个参数

2. thread_return

输出:多线程函数返回值

0:成功

 

 

 

2.3  pthread_exit(void *retal)

void pthread_exit(void *retval);

Using

Parm

Ret

Others

终止一个线程,返回其他线程

1. retval

输出:线程通过调用:

pthread_exit函数终止执行,并返回一个指向某对象的指针。注意:决不能用它返回一个指向局部变量的指针,因为线程调用该函数后,这个局部变量就不存在了,这将引起严重的程序漏洞

 

1.该函数在线程处理函数中被调用,用于终终止并收回该线程。

3.实例


4.附录

4.1           线程的合并与分离

背景线程属于系统资源,占据一定的内存空间。在c或者c++编程中如果通过malloc()或者new分配了一块内存,就必须使用free()或者delete来回收这两块内存,否则会产生注明的内存泄露问题。线程也是如此,有创建就必须得有回收,线程的合并与分离由此而出。

合并 合并是一种主动回收线程资源的方案。当一个进程或者线程调用了针对其他线程的pthread_join()接口,就是线程合并了。这个接口会阻塞调用进程或线程,知道被合并的线程结束为止。当被合并线程结束,pthread_join()接口就会回收这个线程的资源,并将这个线程的返回值返回给合并者。

分离:线程的分离是将线程资源的回收工作交由系统自动来完成,这也就是使得pthread_detach()接口只要拥有一个参数就行了,那就是被分离线句柄。

区别:在使用pthrea_join()后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此,主线程并不希望因为调用pthread_join()而阻塞(因为还要继续处理之后到来的链接),这时可以在子线程中加入代码:pthread_detach(pthread_self())或者在父线程中调用Pthread_detach(thread_id)这将该子线程的状态设置为detached,则改线程运行结束后会自动释放所有的资源。

4.2  线程的属性

在pthread_create()函数中可以指定线程的属性,这个属性由一个线程属性对象(attr)来描述。线程属性对象由pthread_attr_init()接口初始化,并由pthrea_attr_destory()来销毁,完整定义如下:

Int pthread_attr_init(pthread_attr_t *attr);

Int phtread_addr_destory(pthread_attr_t *attr);

1.绑定属性:将某个线程绑定在某个轻进程上。被绑定的线程据欧较高的相应速度,因为操作系统的调用主体是轻进程,绑定线程可以保证在需要的时候它总有一个轻进程可用。

(轻进程和linux系统的内核线程拥有相同的概念,术语内核的调度实体,一个轻进程可以控制一个或多个线程)

int pthread_attr_setscope(pthread_attr_t *att,int scope);

 

attr:线程属性对象。

Scope

   PTHREAD_SCOPE_SYSTEM(绑定的)

   PTHREAD_SCOPE_PROCESS(非绑定)

2.分离属性:前面说过的线程能够被合并和分离,分离属性就是让线程在创建之前就决定它应该是分离的。如果设置了这个属性,就没有必要调用pthread_join()或pthread_detach()来回收线程资源了。

Int pthread_attr_setdetachstat(pthread_attr_t *att,int detachstate);

attr:线程属性对象。

Detachstate:

PTHREAD_CREATE_DETACHED(分离的)

PTHREAD_CREATE_JOINABLE(可合并的,默认)

3.调度属性:线程调度属性有三个:算法、优先级和继承权。

算法:轮询、先进先出、其他(默认)

优先级:linux优先级线程和进程不同。Linux线程优先级是从1-99的数值,数值越大优先级越高。而且只有在轮询或者先进先出调度算法时优先级才有效。其他算法优先级恒为0(此外需要root运行,并且放弃父线程的继承权,即父线程的调度属性)

pthread_attr_setschedpolicy(pthread_attr_t *attr,struct sched_policy)                //设置算法

SCHED_RR(轮询)、SCHED_FIFO(先进先出)和SCHED_OTHER(其他)

Pthread_attr_setscedparam(pthread_attr_t *attr,struct sched_param *parm)            //设置优先级

Sched_param的sched_priority字段设置优先级。

int pthread_attr_Setinheritsched(pthread_attr*attr,int inheritsched)                  //设置继承权

PTHREAD_INHERIT_SCHED(拥有继承权)

PTHREAD_EXPLICIT_SCHED(放弃继承权)

4.堆栈大小:线程的主函数与程序的主函数main()有一个很相似的特性,那就是可以拥有局部变量。虽然同一个京城的线程之间是永祥内存空间的,但是他的局部变量却并不共享。原因就是局部变量存储在堆栈中,而不同的线程拥有不同的堆栈。Linux系统为每个线程默认分配了8MB的堆栈空间,如果觉得这个空间不够用,可以通过修改线程的堆栈大小属性进行扩容

Int ptread_attr_setstacksize(pthread_attr_t *attr,size_t stacksize)

Stacksize:以字节为单位的堆栈大小,线程堆栈不鞥呢小于16KB而且尽量按4KB(32位系统)或2MB(64位系统)的整数倍分配,也就是内存页面大小的整数倍。此外,修改线程堆栈大小是有风险的。

5.满栈警戒区linux为线程堆栈设置了一个满栈警戒区,这个区域一般就是一个页面,术语线程堆栈的一个扩展区域,一旦有代码访问了这个区域就会发出SIGSEGV信号进行通知。虽然满栈警戒区可以起到安全作用,但是也有利弊,就是会白白浪费掉内存空间,对于内存紧张的系统会使系统变得很慢。所以就有了关闭这个警戒区的需求。同时,如果我们修改了线程堆栈的大小,那么系统会认为我们会自己管理堆栈,也会将警戒区取消掉,如果有需要就开其他。

Int pthread_attr_setguardsize(pthread_attr_t *attr,size_t guadsize);

4.3  线程同步

4.3.1互斥锁

互斥锁就是线程之间相互排斥,获得资格的线程排斥其他没有获得资源的线程。Linux使用互斥锁来实现这种机制。在加锁与解锁之间的代码区域叫做临界区,同步执行破坏了线程并行性的初衷,临界区越大破坏得越厉害。所以在实际应用中,应该避免有临界区的出现,实在不行,临界区也要尽量的小。如果缩小临界区都做不到,那还要多线程干嘛?

初始化和销毁互斥锁(主线程中调用)

Int pthread_mutex_init (pthread_mutex_t *mutex,

                   const pthread_mutexattr_t * attr);

Int pthread_mutex_destory(pthread_mutex_t *mutex);

加锁与解锁(线程中调用)

Trylock有点特殊,调用它试图加锁的线程永远不会被系统”拍晕”,只是通过EBUSY来告诉程序员这个锁已经有人用了

Int pthread_mutex_lock(pthread_mutex_t *mutex)

Int pthread_mutex_trylock(pthread_mutex_t *mutex)

Int pthread_mutex_unlock(phtread_mutex_t *mutex);

4.3.2实例

1 0
原创粉丝点击