Joinable threads VS Detached threads
线程有两种运行模式:
- Joinable Mode
- Detached Mode
Joinable Thread & pthread_join()
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
void * threadFunc(void * arg)
{
std::cout << "Thread Function :: Start" << std::endl;
// Sleep for 2 seconds
sleep(2);
std::cout << "Thread Function :: End" << std::endl;
// Return value from thread
return new int(6);
}
int main()
{
// Thread id
pthread_t threadId;
// Create a thread that will funtion threadFunc()
int err = pthread_create(&threadId, NULL, &threadFunc, NULL);
// Check if thread is created sucessfuly
if (err)
{
std::cout << "Thread creation failed : " << strerror(err);
return err;
}
else
std::cout << "Thread Created with ID : " << threadId << std::endl;
// Do some stuff
void * ptr = NULL;
std::cout << "Waiting for thread to exit" << std::endl;
// Wait for thread to exit
err = pthread_join(threadId, &ptr);
if (err)
{
std::cout << "Failed to join Thread : " << strerror(err) << std::endl;
return err;
}
if (ptr)
std::cout << " value returned by thread : " << *(int *) ptr
<< std::endl;
delete (int *) ptr;
return 0;
}
Detached Thread & pthread_detach()
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
void * threadFunc(void * arg)
{
std::cout << "Thread Function :: Start" << std::endl;
std::cout << "Thread Function :: End" << std::endl;
// Return value from thread
return NULL;
}
int main()
{
// Thread id
pthread_t threadId;
// Create a thread that will funtion threadFunc()
int err = pthread_create(&threadId, NULL, &threadFunc, NULL);
// Check if thread is created sucessfuly
if (err)
{
std::cout << "Thread creation failed : " << strerror(err);
return err;
}
else
std::cout << "Thread Created with ID : " << threadId << std::endl;
// Do some stuff
err = pthread_detach(threadId);
if (err)
std::cout << "Failed to detach Thread : " << strerror(err) << std::endl;
// Sleep for 2 seconds because if main function exits, then other threads will
// be also be killed. Sleep for 2 seconds, so that detached exits by then
sleep(2);
std::cout << "Main function ends " << std::endl;
return 0;
}
多线程导致的内存泄漏
#include<stdio.h>
#include<pthread.h>
void run() {
pthread_exit(0);
}
int main () {
pthread_t thread;
int rc;
long count = 0;
while(1) {
if(rc = pthread_create(&thread, 0, run, 0) ) {
printf("ERROR, rc is %d, so far %ld threads created\n", rc, count);
perror("Fail:");
return ‑1;
}
count++;
}
return 0;
}
编译运行一下:
[root@server ~]# cc -lpthread thread.c -o thread
[root@server ~]# ./thread
ERROR, rc is 12, so far 304 threads created
Fail:: Cannot allocate memory
error code 是 12,啥意思呢,perror
函数帮我们打印出其含义:Cannot allocate memory
。很显然,内存不够了。
看看上面的代码发现,创建的每一个线程既没有调用pthread_join
让主线程等待创建出来的线程退出以便清理其占用的栈空间,也没有用pthread_detach
让线程自动清理占用的空间。所有线程执行完后占用空间不释放,最终导致内存不足,造成了所谓的内存泄漏。
检测泄漏
在调用pthread_create
时候如果不设定线程的 stack size,那么 pthread_create 会使用 ulimit -s
中设置的大小作为 stack size。
查看设置:
$ ulimit -s
8192
表示 8192KB,也就是 8MB。
grep 8192 一下 pmap 的输出,然后 count 一下,就是进程所有的 thread 数(包括正在跑的进程和已经结束的 joinable 线程)。
pmap PID | grep 8192 | wc -l
而 通过:
ls /proc/PID/task | wc -l
得到的是正在运行的线程数。
对比一下两者,如果前者一直比后者大,那么可以考虑是 线程泄漏了。