【转】Linux--Linux线程创建与线程属性


转载自  yanxionglu

线程可以看作是轻量级的进程,所有的程序都有一个主线程(main thread),主线程是进程的控制流或执行线程。在多线程程序中,主线程可以创建一个或多个对等线程(peer thread),从这个时间点开始,这些线程就开始并发执行。主线程和对等线程的区别仅在于主线程总是进程中第一个运行的线程。线程有两个优点:资源消耗量少和方便的通信机制。

一、线程创建

需要的头文件:pthread.h

线程标识符:pthread_t

主要线程函数:

(1)创建线程

int pthread_create ( pthread_t *thread,// 指向线程标识符的指针

pthread_attr_t *attr, // 设置线程属性

void *(*start_routine) (void *), //线程运行函数的起始地址

void *arg ); // 运行函数的参数

当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。

(2)结束线程

void pthread_exit (void *retval) ; //函数的返回代码

(3)等待一个线程的结束

int pthread_join (pthread_t th, //被等待的线程标识符

void **thread_return); //一个用户定义的指针,它可以用来存储被等待线程的返回值。

这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。

(4)获取一个线程的ID

pthread_t pthread_self(void); //获取本线程的线程ID。

使用形式:

void thread1(void)

{...}

void thread2(void)

{...}

...

int ret;

pthread_t pt_1;    

pthread_t pt_2;

ret = pthread_create(&pt_1, NULL, (void *)thread1, NULL);

if (ret != 0) {...} /*线程创建失败*/

ret = pthread_create(&pt_2, NULL, (void *)thread2, NULL);

if (ret != 0) {...} /*线程创建失败*/

/*等待线程1、2的结束*/

pthread_join (pt_1, NULL);    

pthread_join (pt_2, NULL);

二、线程属性

需要的头文件:pthread.h

线程属性标识符:pthread_attr_t

属性值不能直接设置,须使用相关函数进行操作,初始化的函数为pthread_attr_init,这个函数必须在pthread_create函数之前调用。

线程属性主要包括如下属性:作用域(scope);栈尺寸(stack size);栈地址(stack address);优先级(priority);分离的状态(detached state);调度策略和参数(scheduling policy and parameters)。默认的属性为非绑定、非分离、缺省的堆栈、与父进程同样级别的优先级。

线程可以在两种竞争域内竞争资源:进程域(process scope):与同一进程内的其他线程;系统域(system scope):与系统中的所有线程。作用域属性描述特定线程将与哪些线程竞争资源。一个具有系统域的线程将与整个系统中所有具有系统域的线程按照优先级竞争处理器资源,进行调度。

关于线程的绑定,牵涉到另外一个概念:轻进程(LWP:Light Weight Process)。轻进程可以理解为内核线程,它位于用户层和系统层之间。系统对线程资源的分配、对线程的控制是通过轻进程来实现的,一个轻进程可以控制一个或多个线程。默认状况下,启动多少轻进程、哪些轻进程来控制哪些线程是由系统来控制的,这种状况即称为非绑定的。绑定状况下,则顾名思义,即某个线程固定的"绑"在一个轻进程之上。被绑定的线程具有较高的响应速度,这是因为CPU时间片的调度是面向轻进程的,绑定的线程可以保证在需要的时候它总有一个轻进程可用。通过设置被绑定的轻进程的优先级和调度级可以使得绑定的线程满足诸如实时反应之类的要求。

线程的分离状态决定一个线程以什么样的方式来终止自己。线程的默认属性是非分离状态,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。而分离线程不是这样子的,它没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。应该根据自己的需要,选择适当的分离状态。设置线程分离状态的函数为:

pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)。

第二个参数可选为PTHREAD_CREATE_DETACHED(分离线程)和 PTHREAD _CREATE_JOINABLE(非分离线程)。

这里要注意的一点是,如果设置一个线程为分离线程,而这个线程运行又非常快,它很可能在pthread_create函数返回之前就终止了,它终止以后就可能将线程号和系统资源移交给其他的线程使用,这样调用pthread_create的线程就得到了错误的线程号。要避免这种情况可以采取一定的同步措施,最简单的方法之一是可以在被创建的线程里调用pthread_cond_timewait函数,让这个线程等待一会儿,留出足够的时间让函数pthread_create返回。设置一段等待时间,是在多线程编程里常用的方法。但是注意不要使用诸如wait()之类的函数,它们是使整个进程睡眠,并不能解决线程同步的问题。

另外一个可能常用的属性是线程的优先级,它存放在结构sched_param中。

常用的几个函数:

(1) pthread_attr_init

功能:        对线程属性变量的初始化。

函数原型:   int pthread_attr_init (pthread_attr_t* attr);

函数传入值:attr:线程属性。

函数返回值:成功:0,失败:-1

(2) pthread_attr_setscope

功能:       设置线程绑定属性。

函数原型:   int pthread_attr_setscope (pthread_attr_t* attr, int scope);

函数传入值:attr:线程属性。

            scope:PTHREAD_SCOPE_SYSTEM(绑定);PTHREAD_SCOPE_PROCESS(非绑定)

函数返回值:同(1)。

(3) pthread_attr_setdetachstate

功能:        设置线程分离属性。

函数原型:    int pthread_attr_setdetachstate (pthread_attr_t* attr, int detachstate);

函数传入值:attr:线程属性。

            detachstate:PTHREAD_CREATE_DETACHED(分离);PTHREAD_CREATE_JOINABLE(非分离)

函数返回值:同(1)。

(4) pthread_attr_setschedpolicy

功能:       设置创建线程的调度策略。

函数原型:int pthread_attr_setschedpolicy(pthread_attr_t* attr, int policy)

函数传入值:attr:线程属性;

            policy:线程调度策略:SCHED_FIFO、SCHED_RR和SCHED_OTHER。

函数返回值:同(1)。

(5) pthread_attr_setschedparam

功能:       设置线程优先级。

函数原型:   int pthread_attr_setschedparam (pthread_attr_t* attr, struct sched_param* param);

函数传入值: attr:线程属性。

             param:线程优先级。

函数返回值:同(1)。

(6) pthread_attr_destroy

功能:        对线程属性变量的销毁。

函数原型:   int pthread_attr_destroy (pthread_attr_t* attr);

函数传入值:attr:线程属性。

函数返回值:同(1)。

(7)其他

int pthread_attr_setguardsize(pthread_attr_t* attr,size_t guardsize);//设置新创建线程栈的保护区大小。

int pthread_attr_setinheritsched(pthread_attr_t* attr, int inheritsched);//决定怎样设置新创建线程的调度属性。

int pthread_attr_setstack(pthread_attr_t* attr, void* stackader,size_t stacksize);//两者共同决定了线程栈的基地址以及堆栈的最小尺寸(以字节为单位)。

int pthread_attr_setstackaddr(pthread_attr_t* attr, void* stackader);//决定了新创建线程的栈的基地址。

int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stacksize);//决定了新创建线程的栈的最小尺寸(以字节为单位)。

例:创建优先级为10的线程。

pthread_attr_tattr;

structsched_paramparam;

pthread_attr_init(&attr);

pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); //绑定

pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); //分离

pthread_attr_setschedpolicy(&attr, SCHED_RR);

param.sched_priority = 10;

pthread_attr_setschedparam(&attr, &param);

pthread_create(xxx, &attr, xxx, xxx);

pthread_attr_destroy(&attr);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值