线程控制1
1.线程创建函数
#include<pthread.h>
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void*(*start_routine)(void*), void *arg);
参数解析
thread:当线程创建成功返回创建线程ID;
attr:指定线程的属性,大多使用NULL表示默认属性
start_routine:函数指针,指向线程创建后要调用的函数。被调用的线程函数也被称为线程函数。
arg:该参数指向传递给线程函数的参数。
注:线程创建成功时,函数会返回0,若返回值不为0则说明线程创建失败。
#include<stdio.h> #include<unistd.h> #include<pthread.h> int thread(void *arg) { printf("how to use pthread_create function %d \n", pthread_self()); return 0; } int main() { pthread_t th;
printf("main function pthread num is %ld \n", pthread_self());
if(pthread_create(&th, NULL,(void*)thread, NULL) != 0) { printf("create pthread failed\n"); exit(1); } sleep(1); return 0; }
运行一下
为啥gcc后边要加 -lpthread呢?
原因是pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用pthread_create()创建线程,以及调用 pthread_atfork()函数建立fork处理程序时,需要链接该库。
看着就像是主程序叫了一个小弟帮他干活,仿佛和主函数调用函数一样,但事实并不是这样。将倒数第二行代码去掉以后会发现线程函数thread并不会被执行,因为主线程结束了则整个进程截止了,此时进程中的所有线程也也将终止,这也是线程和普通函数调用的一大区别。
注:pthread_self()函数即为获取线程号的函数。
2.线程终止
Linux有两种方式可以使线程终止。一种通过return从线程函数返回,另一种是使用pthread_exit()函数退出线程。
这里有两种情况需要注意:
一个情况是上面刚刚提到的main函数返回或者使用了exit函数退出主进程,则进程内所有线程也将终止。
另一个情况是如果只是主线程调用了pthread_exit()函数,仅仅是主线程死亡,进程不会结束,而且在主线程内创建的其他线程也不会被终止,直到所有线程结束,进程才会结束。
例如:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
int thread1(void *arg)
{
printf("2. how to use pthread_create function %ld \n", pthread_self());
return 0;
}
int thread(void *arg)
{
pthread_t th;
printf("1. how to use pthread_create function %ld \n", pthread_self());
if(pthread_create(&th, NULL, (void*)thread1, NULL) != 0)
{
printf("create pthread failed\n");
exit(1);
}
pthread_exit(1);
}
void main()
{
pthread_t th;
printf("main function pthread num is %ld \n", pthread_self());
if(pthread_create(&th, NULL,(void*)thread, NULL) != 0)
{
printf("create pthread failed\n");
exit(1);
}
pthread_exit(1);
}
运行结果
这次主程序并没有挂起来等待线程,而是在最后使用pthread_exit()退出,其他子线程并没受到影响。
在线程中,也有和和进程中的wait函数类似等待线程结束的函数。这个函数就是pthread_join()
#include<pthread.h>
void pthread_exit(void *retval);
int pthread_join(pthread_t th, void *thread_return);
int pthread_detach(pthread_t th);
函数ptread_join用来等待一个线程的结束。pthread_join()的调用者将被挂起等待线程号为th的线程终止,如果th线程退出使用了pthread_exit(),则*thread_return = retval。
注意:一个线程仅能允许被一个线程使用pthread_exit()等待它的终止·,并且被等待的线程应该处于可join状态,不可以为DETACHED状态。DETACHED状态是指某个线程执行pthread_detach()后其所处的状态。处于DETACHED状态的线程无法由pthread_join()同步。
一个可“join”的线程所占用的内存仅当有线程对其执行了pthread_join()后才会释放,因此为避免内存泄漏,所有线程的终止时,要么被设为DETACHED,要么使用pthread_join回收资源。
例程
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
void test(void *arg)
{
printf("T am helping me to understand what's pthread_join\n");
sleep(5);
pthread_exit(6);
}
int main()
{
pthread_t ts;
int status;
pthread_create(&ts, NULL,(void*)test, NULL);
pthread_join(ts, (void*)&status);
printf("test's exit is cause %d\n", status);
return 0;
}
运行结果
“test's exit is cause 6”这句活在上一句打印后约5秒才被打印出来,说明调用pthread_join的线程的确会被挂起等待要等的线程结束才会继续运行。