就像每一个进程都有一个唯一的进程号一样,线程也有一个唯一的线程号,但是这个线程号仅仅在其所在的进程环境中有效。
进程号用pid_t表示一个非负整数,线程号不是系统唯一, 而是进程环境中唯一有效。线程的句柄是pthread_t类型, 该类型不能作为整数处理, 而是一个结构。
1.线程创建
使用pthread_create()函数来创建线程。
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(start_rtn)(void), void *restrict arg);
参数: - tidp: 指向新创建线程ID的变量, 作为函数的输出。 - attr: 用于定制各种不同的线程属性, NULL为默认属性(见下)。 - start_rtn: 函数指针, 为线程开始执行的函数名.该函数可以返回一个void *类型的返回值,而这个返回值也可以是其他类型,并由 pthread_join()获取。 - arg: 函数的唯一无类型(void)指针参数, 如要传多个参数, 可以用结构封装。
返回值: - 成功则返回0, 否则返回错误编号。
注意:线程依赖于进程,如果创建线程的进程结束了,那么线程也就结束了。
实例:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *thr_fn(void *arg)
{
printf("new thread is running...\n");
}
int main(int argc, char const *argv[])
{
printf("main thread is running....\n");
pthread_t thread;
if (pthread_create(&thread, NULL, thr_fn, NULL) != 0)
{
perror("error to pthread_create:");
exit(-1);
}
while(1); //保证主线程不结束...
return 0;
}
测试运行:
注意:多线程程序的编译必须添加-lpthread 参数。
[root@iz2zefozq9h39txdb8s7npz shelldemo]# gcc test_thcreate.c -lpthread
[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
main thread is running....
new thread is running...
^Z
[1]+ Stopped ./a.out
2.线程的调度
多线程执行顺序是不确定的,每个线程轮流使用CPU资源,时间片到后线程切换。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void *thr_fn1(void *arg)
{
printf("new thread1 is running...\n");
sleep(1);
printf("************thread1************\n");
}
void *thr_fn2(void *arg)
{
printf("new thread2 is running...\n");
sleep(1);
printf("************thread2************\n");
}
int main(int argc, char const *argv[])
{
printf("main thread is running....\n");
pthread_t thread;
if (pthread_create(&thread, NULL, thr_fn1, NULL) != 0)
{
perror("error to pthread_create:");
exit(-1);
}
if (pthread_create(&thread, NULL, thr_fn2, NULL) != 0)
{
perror("error to pthread_create:");
exit(-1);
}
while(1); //保证主线程不结束...
return 0;
}
运行结果:
[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
main thread is running....
new thread2 is running...
new thread1 is running...
************thread1************
************thread2************
^Z
3.线程传参
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int num = 100;
void *thr_fn1(void *arg)
{
printf("new thread1 is running...\n");
num++; //修改全局变量num;
int n = *(int*)arg;
printf("in thread1 counter=%d\n",n);
(*(int*)arg)++;
//*(int*)arg=777;
sleep(1);
printf("************thread1************\n");
}
void *thr_fn2(void *arg)
{
sleep(1);
printf("new thread2 is running...\n");
printf("num=%d\n",num);
int n = *(int*)arg;
printf("in thread2 counter=%d\n",n);
printf("************thread2************\n");
}
int main(int argc, char const *argv[])
{
printf("main thread is running....\n");
pthread_t thread;
int counter=666;
//线程传参
if (pthread_create(&thread, NULL, thr_fn1, (void *)&counter) != 0)
{
perror("error to pthread_create:");
exit(-1);
}
if (pthread_create(&thread, NULL, thr_fn2, (void *)&counter) != 0)
{
perror("error to pthread_create:");
exit(-1);
}
while(1); //保证主线程不结束...
return 0;
}
运行结果:
[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
main thread is running....
new thread1 is running...
in thread1 counter=666
new thread2 is running...
num=101
in thread2 counter=667
************thread2************
************thread1************
^Z