#include int pthread_create(pthread_t * thread,const pthread_attr_t * attr,void *(*start_routine)(void*), void * arg);
返回值:成功返回0,失败返回错误号。
thread:成功返回后,新创建的线程的id被填写到 thread
参数所指向的内存单元。线程id的类型是pthread_t
,它只在当前进程中保证是唯一的,在不同的系统中pthread_t
这个类型有不同的实现,它可能是一个整数值,也可能是一个结构体,也可能是一个地址,所以不能简单地当成整数用printf
打印,调用pthread_self()
可以获取当前线程地id。
attr:表示线程属性,这里暂不讨论。
start_routine和arg:新线程所指向的代码由函数指针start_routine
决定。start_routine
函数接收一个参数arg
,该参数的类型为void *
,这个指针按什么类型解释由调用者自己定义,start_routine
的返回值类型也是void *
,这个指针的函数的含义同样由调用者自己定义。
#include
#include
#include
#include static void thread_func(const char *arg)
{printf("arg=%s\n", arg);pthread_t tid = pthread_self();printf("new thread pid=%u\n", (uint32_t)tid);
}int main(void)
{pthread_t id;int ret = pthread_create(&id, NULL, thread_func, "i am iron man");if (0 != ret){printf("pthread_carete error=%s", strerror(ret));}printf("new thread pid=%u\n", (uint32_t)id);while (1){usleep(1000);}return 0;
}
输出结果为:
new thread pid=1
arg=i am iron man
new thread pid=1
可知,在window上,thread_t类型是一个整型值。
如果需要终止某个线程而不终止整个进程,可以有三种方法:
return
。这种方法对主线程不适用,从main
函数return
相当于调用exit
。pthread_cancel
终止同一进程中地另一个线程。pthread_exit
终止自己。在介绍终止之前,我们先介绍一下pthread_join
函数。
#include int pthread_join(pthread_t thread, void **value_ptr);//返回值:成功返回0,失败返回错误号。
调用该函数地线程将挂起等待,直到id为thread
的线程终止。thread
线程以不同的方法终止,通过pthread_join
得到的终止状态时不同的,总结如下:
thread
线程通过return
返回,value_ptr
所指向的单元里存放的是thread
线程函数的返回值。thread
线程被别的线程调用thread_cancel
异常终止掉,value_ptr
所指向的单元里存放的是常数PTHREAD_CANCELED
。thread
线程是自己调用pthread_exit
终止的,value_ptr
所指向的单元里存放的是传给pthread_exit
的参数。如果对thread
线程的终止状态不感兴趣,可以传NULL
给value_ptr
参数。
一般情况下,线程终止后,其终止状态一直保留到其他线程调用pthread_join
获取它的状态为止。但是线程也可以被设置为detach
状态,这样的线程一旦终止就立刻回收它占用的所有资源,而不保留终止状态。不能对一个已经处于detach
状态的线程调用pthread_join
,这样的调用将返回EINVAL
。对一个尚未detach
的线程调用pthread_join
或pthread_detach
都可以把该线程设置为detach状态,也就是说,不能对同一线程调用两次pthread_join
,或者如果已经对一个线程调用了pthread_detach
就不能再调用pthread_join
了。
#include int pthread_detach(pthread_t tid);//返回值:成功返回0,失败返回错误号。
#include
#include
#include
#include static void *thread1_func(const char *arg)
{printf("arg=%s\n", arg);pthread_t tid = pthread_self();printf("new thread pid=%u\n", (uint32_t)tid);return (void *)0xFF;
}static void *thread2_func(const char *arg)
{printf("arg=%s\n", arg);pthread_t tid = pthread_self();printf("new thread pid=%u\n", (uint32_t)tid);pthread_exit((void *)0xFE);
}static void *thread3_func(const char *arg)
{printf("arg=%s\n", arg);pthread_t tid = pthread_self();printf("new thread pid=%u\n", (uint32_t)tid);while (1){printf("%s running\n", arg);usleep(5000 * 100);}
}int main(void)
{pthread_t id1;int ret1 = pthread_create(&id1, NULL, thread1_func, "i am thread1");if (0 != ret1){printf("pthread_carete error=%s", strerror(ret1));}void *thread1_ret;pthread_join(id1, &thread1_ret);printf("thread1_ret=%d\n", (int)thread1_ret);pthread_t id2;int ret2 = pthread_create(&id2, NULL, thread2_func, "i am thread2");if (0 != ret2){printf("pthread_carete error=%s", strerror(ret2));}void *thread2_ret;pthread_join(id2, &thread2_ret);printf("thread2_ret=%d\n", (int)thread2_ret);pthread_t id3;int ret3 = pthread_create(&id3, NULL, thread3_func, "i am thread3");if (0 != ret3){printf("pthread_carete error=%s", strerror(ret3));}void *thread3_ret;sleep(1);pthread_cancel(id3);pthread_join(id3, &thread3_ret);printf("thread3_ret=%d\n", (int)thread3_ret);while (1){usleep(1000);}return 0;
}
输出为:
arg=i am thread1
new thread pid=1
thread1_ret=255
arg=i am thread2
new thread pid=3
thread2_ret=254
arg=i am thread3
new thread pid=4
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
i am thread3 running
我们可以看到,线程1和线程2的终止与我们的预期一样,但是线程3使用pthread_cancel()
似乎没有真正终止线程。那这里就需要引用另外两个概念了。
@state:PTHREAD_CANCEL_ENABLE:线程对cancel信号立即有反应,将设置为CANCEL状态 (默认)PTHREAD_CANCEL_DISABLE:如果线程state为不可取消,线程不理会信号,继续执行,而使用cancel函数的线程会一直阻塞到可取消状态@oldstate:NULL:state写入有效,即当前只想设置属性,而不关心原来的属性不为NULL:state不写入,保持原有的设定,且获取原来的属性return:成功返回0,错误返回errno EINVAL:无效的stateint pthread_setcancelstate(int state,int *oldstate)
@type:PTHREAD_CANCEL_DEFERRED:运行到下一个取消点就退出 (默认)PTHREAD_CANCEL_ASYNCHRONOUS:直接退出@oldtyoe:NULL:type写入有效,即当前只想设置属性,而不关心原来的属性不为NULL:type不写入,保持原有的设定,且获取原来的属性return:成功返回0,错误返回errno EINVAL:无效的type
int pthread_setcanceltype(int type,int *oldtype)
所以,如下想要使用pthread_cancel
终止线程,那么我们必须在线程函数中调用
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
当我们把线程函数改成:
static void *thread3_func(const char *arg)
{pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);printf("arg=%s\n", arg);pthread_t tid = pthread_self();printf("new thread pid=%u\n", (uint32_t)tid);while (1){printf("%s running\n", arg);usleep(5000 * 100);}
}
那么就可以正常终止了,输出结果如下:
arg=i am thread1
new thread pid=1
thread1_ret=255
arg=i am thread2
new thread pid=3
thread2_ret=254
arg=i am thread3
new thread pid=4
i am thread3 running
i am thread3 running
thread3_ret=-559038737
上一篇:如何提升权限运行远程桌面客户端?