创建线程,等待线程终止
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void f(void)
{
for(int i=0; i<3; ++i)
printf ("This is a pthread.\n");
}
int main(void)
{
pthread_t id;
// 线程创建
int ret = pthread_create(&id, // 线程标识符
NULL, // 线程属性
/*
如果未指定属性对象,则该对象为NULL,系统会创建具有以下属性的缺省线程:
1、进程范围
2、非分离
3、缺省栈和缺省栈大小
4、零优先级
还可以用pthread_attr_init()创建缺省属性对象,然后使用该属性对象来创建缺省线程。
*/
(void*)f, // 线程运行函数的起始地址
NULL); // 运行函数的参数
printf("%d\n", ret);
// 返回值ret
// 0: 创建成功
// EAGAIN: 超出了系统限制,如创建的线程太多。
// EINVAL: 属性值无效。
if(ret != 0)
{
printf("Create pthread error!\n");
exit(1);
}
for(int i=0; i<3; ++i)
{
printf("This is the main process.\n");
// 等待一个线程的结束
// 指定的线程必须位于当前进程中,不可以是分离线程
// 应用程序可回收与已终止线程关联的任何数据存储空间
// 代码中如果没有pthread_join()函数,主函数会很快结束从而使整个进程结束
// 从而使创建的线程没有机会开始执行就结束了
int ret1 = pthread_join(id, // 被等待线程的标识符
NULL); // 用户定义的指针,存储被等待线程返回值
// 返回值ret1
// 0: 成功
// ESRCH: 没有找到与给定的线程ID相对应的线程
// EDEADLK: 将出现死锁,如一个线程等待其本身,或者线程A和线程B互相等待
// EINVAL: 与给定的线程ID相对应的线程是分离线程
return 0;
}
return 0;
}
分离线程
pthread_detach()可以显式用于分离线程,尽管创建时是可连接的。
创建一个线程默认的状态是joinable, 如果一个线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process,即还有一部分资源没有被回收(退出状态码),所以创建线程者应该使用pthread_join()来等待线程运行结束,并可得到线程的退出代码,回收其资源(类似于wait,waitpid)。但是调用pthread_join()后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此,比如在Web服务器中当主线程为每个新来的链接创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的链接),这时可以在子线程中加入代码
pthread_detach(pthread_self());
或在主线程中调用
pthread_detach(thread_id);//非阻塞,可立即返回
这将使该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源。
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int count = 0;
void print()
{
printf("%d\n", count++);
pthread_exit(0);
sleep(1000);
}
int main()
{
pthread_t id;
while(1)
{
pthread_create(&id, NULL, (void*)print, NULL);
pthread_detach(id);
}
return 0;
}
线程优先级
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
void myfunc(void *a)
{
printf("a: %d\n", *(int*)a);
pthread_exit(0); // 线程退出
}
int main()
{
pthread_attr_t attr;
pthread_t tid;
struct sched_param param;
int newprio = 20;
// 先取线程优先级,然后修改,最后放回去
pthread_attr_init(&attr); // 创建缺省属性对象
pthread_attr_getschedparam(&attr, ¶m); // 获取线程属性
printf("priority1: %d\n", param.sched_priority);
param.sched_priority = newprio;
pthread_attr_setschedparam(&attr, ¶m); // 设置线程属性
printf("priority2: %d\n", param.sched_priority);
int myarg = 3;
int ret = pthread_create(&tid, &attr, (void*)myfunc, (void*)&myarg);
printf("ret: %d\n", ret);
pthread_join(tid, NULL);
return 0;
}
参考
Linux多线程编程讲稿 https://wenku.baidu.com/view/e5d90e40336c1eb91a375da8.html
https://www.cnblogs.com/CodeMIRACLE/p/5491583.html
多线程编程指南