#include <stdio.h>
#include <error.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
void work1(void *arg)
{
char *mem1 = (char *)malloc(100);
free(mem1);
}
void work2(void *arg)
{
char *mem2 = (char *)malloc(100);
free(mem2);
}
int main()
{
pthread_t thread_id1, thread_id2;
pthread_create(&thread_id1, NULL, (void *)work1, NULL);
pthread_create(&thread_id2, NULL, (void *)work2, NULL);
//pthread_detach(thread_id1);
pthread_join(thread_id2, NULL);
sleep(3);
printf("%ld %ld", thread_id1, thread_id2);
return 0;
}
对pthread传统要用pthread_join函数等待其结束,实际上pthread_join函数还有另一个功能:清理线程的资源。
因为有时候开启线程后并不关心线程什么时候结束,此时就需要使用pthread_detach来将线程分离。被分离的线程将由操作系统自动回收其资源。
也就意味着上述代码出现了一处内存泄露,因为线程1既没有被分离,也没有使用pthread_join等待其完成。
PS:(1)操作系统只会回收线程本身的资源开销,并不会回收线程在堆上分配的内存。假如将函数work1和work2中的内存释放语句free注释掉的话,本例中的内存泄露将会达到三处。
(2)内存泄露可使用valgrind --tool=memcheck --leak-check=full ./a.out来检测。检测前必须安装valgrind且程序编译要加上-g选项。
(3)线程在创建的时候可将属性设置为分离,这样就自动具备了分离属性,就无需显示调用pthread_detach了。
下面来看C++11中的线程的分离。与pthread原理类似。
#include <iostream>
#include <thread>
using namespace std;
void work()
{
cout << std::this_thread::get_id() << endl;
}
int main()
{
thread t1(work);
thread t2(work);
t1.join();
t2.detach();
return 0;
}
代码是不是简洁了不少?
需要注意的是不管是将线程t1的join函数注释,或是将t2的detach注释掉,程序都会崩溃。为什么呢?
因为C++有异常机制,而本例中没有对异常进行捕获。
以上两个例子测试系统是ubuntu 14.04.3,gcc(g++)的版本是4.6.3。