线程的概念
在一个程序里的多个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列” 一切进程至少都有一个执行线程
线程的优点
创建一个新线程的代价要比创建一个新进程小得多 与进程之间的切换相比,线程之间的切换需要操作系统做的工作至少在理论上要少很多 线程占用的资源要比进程少很多
线程的函数使用
与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”打头的 要使用这些函数库,要通过引入头文件<pthread.h> 链接这些线程函数库时要使用编译器命令的“-lpthread”选项
创建线程函数
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void*(*start_routine)(void*), void *arg);
函数参数的理解:
thread:新线程创建成功后,保存新线程的标识符 attr:设置线程的属性,一般不需要什么特殊的属性,直接传 NULL即可 start_routine: 是个函数地址,线程启动后要执行的函数 arg:传给线程启动函数的参数“void* (*start_routine)(void*) ”表示需要我们传递的一个函数地址,该函数以一个指向void的指针为参数,返回的也是一个指向void的指针。 调用成功时返回值是“0”,如果失败则返回一个错误。
接下来就来一段代码:(下面代码实现两个线程,task_set_name函数是给线程设置名字)
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<sys/syscall.h>
#include<sys/prctl.h>
int task_set_name(const char *name)
{
char thread_name[128]={0};
if(!name)
return -1;
snprintf(thread_name,sizeof(thread_name),"%s(%ld)",name,syscall(SYS_gettid));
prctl(PR_SET_NAME,thread_name,0,0,0);
return 0;
}
void *routine1 (void *arg[])
{
char *pbuf=(char *)arg;
int i;
task_set_name("aa");
printf("%s,pid = 0x%08x\n",pbuf,(int)pthread_self());
for(;i<5;i++)
{
putchar('A');
fflush(stdout);
sleep(1);
}
pthread_exit("pthread1");
return 0;
}
void *routine2(void *arg[])
{
char *pbuf=(char *)arg;
int i;
printf("%s,pid = 0x%08x\n",pbuf,(int)pthread_self());
for(;i<5;i++)
{
putchar('B');
fflush(stdout);
sleep(1);
}
pthread_exit("pthread2");
return 0;
}
int main(int argc,char *argv[])
{
int i;
char *thread_buf = "this is first!\n";
pthread_t tid,tid1;
//1.创建线程1
int ret = pthread_create(&tid,NULL,routine1,thread_buf);
if(ret < 0)
{
fprintf(stderr,"thread create failed:%s\n",strerror(ret));
}
ret = pthread_create(&tid1,NULL,routine2,thread_buf);
if(ret != 0)
{
fprintf(stderr,"thread create faile:%s\n",strerror(ret));
}
sleep(2);
for(i = 0;i<5;i++)
{
putchar('c');
fflush(stdout);
}
//2.等待线程回收
char *pre;
pthread_join(tid,(void**)&pre);
printf("======%s\n",pre);
pthread_join(tid1,(void**)&pre);
printf("=====%s\n",pre);
return 0;
}
代码结果
首先我看看到两个线程被创建,接下来就是两个线程里面实现rountine1和rountine2都是个函数地址,线程启动后要执行的函数
分别执行输出A和B,接下来就是主函数输出c,最后就是线程回收