1.线程的终止
注意该函数是针对用户级别的, 其中 retal 必须指向一个全局变量, 或者是一个 malloc 分配的, 因为如果是线程的局部变量, 当该线程退出时, 其他线程不能得到这个变量, 因为线程的局部变量各自私有
2. 现成的取消
其中thread是线程的 tid
3.线程的等待与分离
(1)线程的等待
注意已经退出的线程它的空间并没有被释放, 它所占有的空间仍然在进程内部, 并且进程创建的新的线程不会复用退出线程的空间, 因此对于已经推出的线程而言, 它所占有的空间必须由主线程将其回收. 因为如果主线程不对退出的线程进行空间回收的, 会造成资源泄露.
上面函数中 thread是线程的tid, 而retval 是一个指针, 这个指针指向一个指针, 它所指向的这个指针指向线程的返回值(对retval进行一次解引用, 可以获取到线程的返回值), 同样成功时返回 0, 失败时返回错误码.. 调用该函数的线程将会被挂起等待, 直到 id 为thread 的线程终止.
线程退出的几种情况
1)代码跑完结果正确,
2)代码跑完结果错误
线程通过不同方式退出, retval所指向的内容是不同的
1)如果线程线程是调用了return 终止(主线程不能用, 因为main 函数调用return相当于进程退出), retval 指向线程函数的返回值
2)如果线程被其他线程调用了 pthread_cancle , 此时 retval 会指向一个常数, PTHREAD_CANCLED, 该常数是被进行了宏定义为 -1
3)如果该函数是自己调用了 pthread_exit, retval 指向传给pthread_exit 的参数的地址
4)如果对线程的退出状态不关心, 此时retval可以被设为 NULL
来看一段代码
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>void* thread1(void* arg)
{printf("I am thread1\n");int* p = (int*)malloc(sizeof(int));*p = 1;return (void*)p;
}void* thread2(void* arg)
{printf("I am thread2\n");int* p = (int*)malloc(sizeof(int));*p = 2;pthread_exit((void*)p);
}void* thread3(void* arg)
{while(1){printf("I am thread3\n");sleep(1);}return NULL;
}
int main()
{pthread_t tid;void* ret;pthread_create(&tid, NULL, thread1, (void*)1);pthread_join(tid, &ret);printf("tid = %x, ret = %d\n", tid, *(int*)ret);pthread_create(&tid, NULL, thread2, NULL);pthread_join(tid, &ret);printf("tid = %x, ret = %d\n", tid, *(int*)ret);pthread_create(&tid, NULL, thread3, NULL);sleep(3);pthread_cancel(tid);pthread_join(tid, &ret);if(ret == PTHREAD_CANCELED){printf("tid = %x, ret = %d\n", tid, PTHREAD_CANCELED);}return 0;
}
由上图可以看出, 由于线程的终止方式采用了不同的方式终止, 一次返回值 ret 所指向的单元存放的信息也是不同的.而其中的 tid 是相同的那是因为 pthread_create 是用户级别的调用, 而在用户眼里,这个 tid 就是一个地址
(2)线程的分离
默认情况下, 线程是可分离的(线程在退出时必须对其空间进行回收, 否则会造成内存泄露), 因此必须对线程进行等待, 但是当我们不再关心线程的返回值的时候, 此时我们就可以对线程进行分离. 即当线程退出的时候, 我们可以采用一种机制, 告诉操作系统, 该线程就要退出了, 此时, 操作系统便可以在线程退出时自动将该线程的资源释放.其中一个线程可以被别的线程分离, 也可以自己分离自己
其中 pthrea_self 用来获取线程自身的 tid
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h>
#include<stdlib.h>void* thread1(void* arg)
{printf("%s\n", (char*)arg);pthread_detach(pthread_self());return NULL;
}
int main()
{pthread_t thread;int result;void* ret;if(pthread_create(&thread, NULL, thread1, "thread1 is running") != 0){printf("create thtread is failed\n");return 1;}sleep(1);if(pthread_join(thread, NULL) == 0){printf("wait thread is sucessful\n");result = 0;}else{printf("wait thread is failed\n");result = 1;}return result;
}
在上图中, 由于线程已经分离, 但是我们还对其进行 join, 此时必定join 失败, 即对一个已经分离的线程不能再进行 join