线程创建函数:
#include
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void*), void *arg);
参数
thread:返回线程ID。
attr:设置线程的属性,attr为NULL表⽰示使⽤用默认属性。
start_routine:是个函数地址,线程启动后要执⾏行的函数。
arg:传给线程启动函数的参数。
返回值:成功返回0;失败返回错误码。
一般用pthread_create函数创建新线程。下面是利用pthread_create函数创建新线程的代码:
#include
#include
#include
#include
#include
void *thread_run(void *arg)
{
while(1)
{
printf("I am a thread!\n");
sleep(1);
}
}
int main(void)
{
pthread_t tid;
pthread_create(&tid, NULL, thread_run, NULL);
while(1)
{
printf("I am thread group!\n");
sleep(1);
}
return 0;
}
也可以取得线程的线程ID:
#include
pthread_t pthread_self(void);
返回值:调用线程的ID。
这里取得线程库pthread范围的线程ID,返回值为pthread_t类型数据, pthread_t 的具体类型取决于实现,Linux的NPTL实现中,pthread_t类型的线程ID,本质上是一个进程地址空间的地址。
也可以用:
#define _GNU_SOURCE
#include
#include
pid_t tid;
tid = syscall(SYS_gettid);
这里取得内核级线程的线程ID,即pid。
可以将上面的代码稍微改一下:
#include
#include
#include
#include
#include
#include
#define _GNU_SOURCE
void *thread_run(void *arg)
{
pthread_t tid = pthread_self();
pid_t pid = syscall(SYS_gettid);
while(1)
{
printf("I am a thread! user: %p, kernel: %d\n", tid, pid);
sleep(1);
}
}
int main(void)
{
pthread_t tid;
pthread_create(&tid, NULL, thread_run, NULL);
pthread_t ptid = pthread_self();
pid_t pid = syscall(SYS_gettid);
while(1)
{
printf("I am thread group! user: %p, kernel: %d\n", ptid, pid);
sleep(1);
}
return 0;
}
在多线程进程中,任何一个线程的异常终止都会导致整个进程的退出,如果仅要求线程退出而不终止整个进程可用下面三种方法:
1. 从线程函数return。这种⽅方法对主线程不适⽤用,从main函数return相当于调⽤用exit。
2. 线程可以调⽤用pthread_ exit终⽌止⾃自⼰己。
3. ⼀一个线程可以调⽤用pthread_ cancel终⽌止同⼀一进程中的另⼀一个线程。
pthread_exit函数:
void pthread_exit(void *value_ptr);
功能:进程终止。
参数
value_ptr:value_ptr不要指向⼀个局部变量。
返回值:⽆返回值,跟进程一样,线程结束的时候⽆无法返回到它的调用者(自身)。
注意,这里的返回值必须是全局的或用malloc分配的,不能是函数栈上的指针,因为当其他线程得到这个返回值时线程函数已经退出了。
pthread_cancel函数:
int pthread_cancel(pthread_t thread);
功能:取消一个执行中的线程。
参数
thread:线程ID。
返回值:成功返回0;失败返回错误码
要取得线程的返回值,就要用到进程等待函数pthread_join:
int pthread_join(pthread_t thread, void **value_ptr);
功能:等待线程结束,调用该函数的线程将挂起等待,直到id为thread的线程终⽌。
参数
thread:线程ID
value_ptr:它指向⼀个指针,后者指向线程的返回值
返回值:成功返回0;失败返回错误码
新创建的线程默认为是joinable的,即可结合的,当线程退出后必须进程pthread_join操作。因为线程退出后其空间不能自动释放,必须显式回收,如果不进行释放的话新创建的线程不会复用刚刚的地址空间,这样就造成了内存泄漏。
线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:
1. 如果thread线程通过return返回,value_ ptr所指向的单元⾥里存放的是thread线程函数的返回值。
2. 如果thread线程被别的线程调用pthread_ cancel异常终掉,value_ ptr所指向的单元里存放的是常数PTHREAD_ CANCELED。
3. 如果thread线程是自己调用pthreadexit 终止的 ,valueptr所指向的单元存放的是传给pthread_exit的参数。
4. 如果对thread线程的终止状态不感兴趣,可以传NULL给value_ ptr参数。
代码:
#include
#include
#include
#include
#include
#include
#define _GNU_SOURCE
void *thread_run1(void *arg)
{
printf("%s\n", (char*)arg);
int *p = (int*)malloc(sizeof(int));
*p = 1;
sleep(2);
return (void*)p;
}
void *thread_run2(void *arg)
{
printf("%s\n", (char*)arg);
int *p = (int*)malloc(sizeof(int));
*p = 2;
sleep(2);
pthread_exit((void*)p);
}
void *thread_run3(void *arg)
{
printf("%s\n", (char*)arg);
while(1);
}
int main(void)
{
pthread_t tid1, tid2, tid3;
void *ret1, *ret2, *ret3;
pthread_create(&tid1, NULL, thread_run1, "thread No1");
pthread_create(&tid2, NULL, thread_run2, "thread No2");
pthread_create(&tid3, NULL, thread_run3, "thread No3");
//sleep(1);
pthread_cancel(tid3);
pthread_join(tid1, &ret1);
printf("thread quit! thread id : %X, return code : %d\n", tid1, *(int*)ret1);
free(ret1);
pthread_join(tid2, &ret2);
printf("thread quit! thread id : %X, return code : %d\n", tid2, *(int*)ret2);
free(ret2);
pthread_join(tid3, &ret3);
if(ret3 == PTHREAD_CANCELED)
printf("thread quit! thread id : %X, return code : PTHREAD_CANCELED\n", tid3);
else
printf("thread quit! thread id : %X, return code : NULL\n", tid3);
return 0;
}
新创建的线程是可结合的,即需要调用pthread_join进行回收,而如果不需要线程函数的返回值,那么join就是一种负担,此时我们可以将线程声明为“分离”的,即当线程结束后系统自动释放线程资源。
#include
int pthread_detach(pthread_t thread);
功能:对线程thread进行分离。
返回值:成功返回0;错误返回错误编号。
线程也可以自己分离:
pthread_detach(pthread_self());
joinable与分离是冲突的,因此一个线程不能同时是joinable和分离的。
代码:
#include
#include
#include
#include
#include
#include
#define _GNU_SOURCE
void *thread_run(void *arg)
{
pthread_detach(pthread_self());
printf("%s\n", (char*)arg);
return NULL;
}
int main(void)
{
pthread_t tid;
if(pthread_create(&tid, NULL, thread_run, "thread run") != 0)
{
printf("create thread errno\n");
return 1;
}
printf("I am thread group!\n");
sleep(1);
if(pthread_join(tid, NULL) == 0)
printf("thread wait success\n");
else
printf("thread wait failed\n");
return 0;
}
先派生出一个线程,这个线程自己分离后执行后续操作,主线程调用pthread_join,如果等待成功则输出“thread wait success”,失败则输出“thread wait failed”,来看运行结果:
显然派生出的线程自动进行线程分离,主线程等待失败。