多线程编程之pthread_create pthread_join pthread_attr_t
2017-06-22 18:37
417 查看
多线程编程之pthread_create函数应用
pthread_create函数
函数简介
pthread_create是UNIX环境创建线程函数
头文件
#include<pthread.h>
函数声明
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void* (*start_routine)(void *), void *arg);
返回值
若成功则返回0,否则返回出错编号
参数
第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址。
最后一个参数是运行函数的参数。
另外
pthread库不是Linux系统默认的库,连接时需要使用静态库libpthread.a,所以在线程函数在编译时,需要连接库函数
pthread_join函数
函数简介
函数pthread_join用来等待一个线程的结束。
函数原型为:
int pthread_join(pthread_t thread, void **value_ptr);
参数:
第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。如果执行成功,将返回0,如果失败则返回一个错误号。
举例:
/*thread.c*/
#include <stdio.h>
#include <pthread.h>
/*线程一*/
void thread_1(void)
{
int i=0;
for(i=0;i<=6;i++)
{
printf("This is a pthread_1.\n");
if(i==2)
pthread_exit(0);
sleep(1);
}
}
/*线程二*/
void thread_2(void)
{
int i;
for(i=0;i<3;i++)
printf("This is a pthread_2.\n");
pthread_exit(0);
}
int main(void)
{
pthread_t id_1,id_2;
int i,ret;
/*创建线程一*/
ret=pthread_create(&id_1,NULL,(void *) thread_1,NULL);
if(ret!=0)
{
printf("Create pthread error!\n");
return -1;
}
/*创建线程二*/
ret=pthread_create(&id_2,NULL,(void *) thread_2,NULL);
if(ret!=0)
{
printf("Create pthread error!\n");
return -1;
}
/*等待线程结束*/
pthread_join(id_1,NULL);
pthread_join(id_2,NULL);
return 0;
}
以下是程序运行结果:
备注:pthread库不是Linux系统默认的库,连接时需要使用静态库libpthread.a,所以在线程函数在编译时,需要连接库函数,如上图
gcc pthread_create.c -o pthread_create -lpthread
线程属性
线程具有属性,用pthread_attr_t表示,在对该结构进行处理之前必须进行初始化,在使用后需要对其去除初始化。我们用pthread_attr_init函数对其初始化,用pthread_attr_destroy对其去除初始化。
1.
调用pthread_attr_init之后,pthread_t结构所包含的内容就是操作系统实现支持的线程所有属性的默认值。
如果要去除对pthread_attr_t结构的初始化,可以调用pthread_attr_destroy函数。如果pthread_attr_init实现时为属性对象分配了动态内存空间,pthread_attr_destroy还会用无效的值初始化属性对象,因此如果经pthread_attr_destroy去除初始化之后的pthread_attr_t结构被pthread_create函数调用,将会导致其返回错误。
线程属性结构如下:
typedef struct
{
int detachstate; 线程的分离状态
int schedpolicy; 线程调度策略
structsched_param schedparam; 线程的调度参数
int inheritsched; 线程的继承性
int scope; 线程的作用域
size_t guardsize; 线程栈末尾的警戒缓冲区大小
int stackaddr_set;
void* stackaddr; 线程栈的位置
size_t stacksize; 线程栈的大小
}pthread_attr_t;
每个个属性都对应一些函数对其查看或修改。下面我们分别介绍。
大致步骤为:
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setXXX(&attr,
目标值);
……//创建线程,其他代码
pthread_attr_destroy(&attr);
通过一系列的set函数设置pthread_attr_t类型结构体attr的值。
1.线程分离状态
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int*detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *attr, intdetachstate);
设置线程的分离状态为PTHREAD_CREATE_JOINABLE或PTHREAD_CREATE_DETACHED。
默认是joinable,有一些资源会在线程结束后仍然保持占用状态,直到另外的线程对这个线程使用pthread_join。detached线程不是这样子的,它没有被其他的线程所等待(join),自己运行结束了,线程也就终止了,马上释放系统资源。
若成功返回0,若失败返回-1。
2.线程的调度策略
int pthread_attr_getschedpolicy(const pthread_attr_t *restrict attr,
int *restrict policy);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
设置调度策略为SCHED_OTHER、SCHED_FIFO、SCHED_RR。默认调度为other。
若成功返回0,若失败返回-1。
3.线程的调度参数
int pthread_attr_getschedparam(const pthread_attr_t *restrict attr,
struct sched_param *restrictparam);
int pthread_attr_setschedparam(pthread_attr_t *restrict attr,
const struct sched_param*restrict param);
结构param的子成员__sched_priority控制一个优先权值,大的优先权值对应高的优先权。
若成功返回0,若失败返回-1。
4.线程的继承调度
int pthread_attr_getinheritsched(constpthread_attr_t *restrict attr,
int*restrict inheritsched);
int pthread_attr_setinheritsched(pthread_attr_t*attr, int inheritsched);
设置线程是否继承父线程的调度,即此线程的调度策略及优先级是继承于父线程,还是通过set设定两个属性。值为:PTHREAD_INHERIT_SCHED,PTHREAD_EXPLICIT_SCHED。
默认是inherit继承父线程的。
若成功返回0,若失败返回-1。
5.线程的竞争范围
int pthread_attr_getscope(const pthread_attr_t *restrict attr,
int *restrict contentionscope);
int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope);
定义创建的线程的竞争范围为PTHREAD_SCOPE_SYSTEM、PTHREAD_SCOPE_PROCESS。
Linux Threads只实现了PTHREAD_SCOPE_SYSTEM,这意味着,它将和机器上运行的所有进程竞争CPU时间。
标准指定的另外一个值,PTHREAD_SCOPE_PROCESS,表示竞争只存在于运行中的进程的线程之间:即,线程的优先级是相对于其它进程中的线程的优先级的,而不必考虑进程的优先级如何。LinuxThread不支持PTHREAD_SCOPE_PROCESS。
若成功返回0,若失败返回-1。
6.线程的栈的地址和大小
(1)
int pthread_attr_getstack(pthread_attr_t *attr,void **stackaddr,size_t*stacksize);
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,size_t stacksize);
设置线程栈的起始地址和栈大小。默认起始地址0,大小0x800000(8M,我的机子……)。
PS:使用get时往往显示的是addr
= 0,size = 0,这可能是系统的BUG,size应给为8M而不是0。
(2)
上面的2个函数可以细化成4个:
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);
int pthread_attr_getstackaddr(pthread_attr_t *attr, void**stackaddr);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_tstacksize);
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t*stacksize);
这里get得到的size为8M,所以pthread_attr_getstack获得的size大小是不能说明栈的大小的。
7.栈溢出保护区大小
intpthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
intpthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);
设置线程的栈溢出保护区大小,默认4096B,即4K。
8.
设置/获取线程属性对象里CPU
姻亲属性
int pthread_attr_setaffinity_np(pthread_attr_t *attr,size_tcpusetsize,
const cpu_set_t *cpuset);
int pthread_attr_getaffinity_np(pthread_attr_t *attr, size_tcpusetsize,
cpu_set_t *cpuset);
函数把 attr
引用的线程属性对象中的 CPU
姻亲掩码设置为cpuset
指定的值。这个属性决定了使用线程属性对象 attr
创建的线程的 CPU
姻亲掩码。
举例说明:
int anyka_pthread_create(pthread_t *thread_id, anyka_thread_main *func, void *arg, int stack_size, int priority)
{
int ret;
pthread_attr_t SchedAttr;
struct sched_param SchedParam;
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
//anyka_print("pthread priority(SCHED_RR)=(min=%d,max=%d)\n", sched_get_priority_min(SCHED_RR), sched_get_priority_max(SCHED_RR));
//anyka_print("pthread priority(SCHED_FIFO)=(min=%d,max=%d)\n", sched_get_priority_min(SCHED_FIFO), sched_get_priority_max(SCHED_FIFO));
#endif
/** init sched param attribute **/
pthread_attr_init(&SchedAttr);
if(priority != -1)
{
ret = pthread_attr_setinheritsched(&SchedAttr, PTHREAD_EXPLICIT_SCHED);
if (ret != 0)
anyka_print("pthread_attr_setschedpolicy, %s\n", strerror(ret));
ret = pthread_attr_setschedpolicy(&SchedAttr, SCHED_RR);
if (ret != 0)
anyka_print("pthread_attr_setschedpolicy, %s\n", strerror(ret));
SchedParam.sched_priority = priority;
ret = pthread_attr_setschedparam(&SchedAttr, &SchedParam);
if (ret != 0)
anyka_print("pthread_attr_setschedparam, %s\n", strerror(ret));
}
ret = pthread_attr_setstacksize(&SchedAttr, stack_size);
if (ret != 0)
anyka_print("pthread_attr_setstacksize, %s\n", strerror(ret));
ret = pthread_create(thread_id, &SchedAttr, func, arg);
if(ret != 0)
anyka_print("pthread_create [ %x ] failed, %s\n", (unsigned int)*func, strerror(ret));
pthread_attr_destroy(&SchedAttr);
return ret;
}
#include <string.h>
#include<pthread.h>
#include<sched.h>
void *child_thread(void *arg)
{
int policy = 0;
int max_priority = 0,min_priority = 0;
struct sched_param param;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED);
pthread_attr_getinheritsched(&attr,&policy);
if(policy == PTHREAD_EXPLICIT_SCHED){
printf("Inheritsched:PTHREAD_EXPLICIT_SCHED\n");
}
if(policy == PTHREAD_INHERIT_SCHED){
printf("Inheritsched:PTHREAD_INHERIT_SCHED\n");
}
pthread_attr_setschedpolicy(&attr,SCHED_RR);
pthread_attr_getschedpolicy(&attr,&policy);
if(policy == SCHED_FIFO){
printf("Schedpolicy:SCHED_FIFO\n");
}
if(policy == SCHED_RR){
printf("Schedpolicy:SCHED_RR\n");
}
if(policy == SCHED_OTHER){
printf("Schedpolicy:SCHED_OTHER\n");
}
max_priority = sched_get_priority_max(policy);
min_priority = sched_get_priority_min(policy);
printf("Maxpriority:%u\n",max_priority);
printf("Minpriority:%u\n",min_priority);
param.sched_priority = max_priority;
pthread_attr_setschedparam(&attr,¶m);
printf("sched_priority:%u\n",param.sched_priority);
pthread_attr_destroy(&attr);
}
int main(int argc,char *argv[])
{
pthread_t child_thread_id;
pthread_create(&child_thread_id, NULL, child_thread,NULL);
pthread_join(child_thread_id, NULL);
}
==[23]==gaoke@dev64_23:~/code$g++ -o test gaoke.cpp -lpthread
==[23]==gaoke@dev64_23:~/code$./test
Inheritsched:PTHREAD_EXPLICIT_SCHED
Schedpolicy:SCHED_RR
Maxpriority:99
Minpriority:1
sched_priority:99
pthread_create函数
函数简介
pthread_create是UNIX环境创建线程函数
头文件
#include<pthread.h>
函数声明
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void* (*start_routine)(void *), void *arg);
返回值
若成功则返回0,否则返回出错编号
参数
第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址。
最后一个参数是运行函数的参数。
另外
pthread库不是Linux系统默认的库,连接时需要使用静态库libpthread.a,所以在线程函数在编译时,需要连接库函数
pthread_join函数
函数简介
函数pthread_join用来等待一个线程的结束。
函数原型为:
int pthread_join(pthread_t thread, void **value_ptr);
参数:
第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。如果执行成功,将返回0,如果失败则返回一个错误号。
举例:
/*thread.c*/
#include <stdio.h>
#include <pthread.h>
/*线程一*/
void thread_1(void)
{
int i=0;
for(i=0;i<=6;i++)
{
printf("This is a pthread_1.\n");
if(i==2)
pthread_exit(0);
sleep(1);
}
}
/*线程二*/
void thread_2(void)
{
int i;
for(i=0;i<3;i++)
printf("This is a pthread_2.\n");
pthread_exit(0);
}
int main(void)
{
pthread_t id_1,id_2;
int i,ret;
/*创建线程一*/
ret=pthread_create(&id_1,NULL,(void *) thread_1,NULL);
if(ret!=0)
{
printf("Create pthread error!\n");
return -1;
}
/*创建线程二*/
ret=pthread_create(&id_2,NULL,(void *) thread_2,NULL);
if(ret!=0)
{
printf("Create pthread error!\n");
return -1;
}
/*等待线程结束*/
pthread_join(id_1,NULL);
pthread_join(id_2,NULL);
return 0;
}
以下是程序运行结果:
备注:pthread库不是Linux系统默认的库,连接时需要使用静态库libpthread.a,所以在线程函数在编译时,需要连接库函数,如上图
gcc pthread_create.c -o pthread_create -lpthread
线程属性
线程具有属性,用pthread_attr_t表示,在对该结构进行处理之前必须进行初始化,在使用后需要对其去除初始化。我们用pthread_attr_init函数对其初始化,用pthread_attr_destroy对其去除初始化。
1.
名称:: | pthread_attr_init/pthread_attr_destroy |
功能: | 对线程属性初始化/去除初始化 |
头文件: | #include<pthread.h> |
函数原形: | int pthread_attr_init(pthread_attr_t*attr); int pthread_attr_destroy(pthread_attr_t*attr); |
参数: | Attr 线程属性变量 |
返回值: | 若成功返回0,若失败返回-1。 |
调用pthread_attr_init之后,pthread_t结构所包含的内容就是操作系统实现支持的线程所有属性的默认值。
如果要去除对pthread_attr_t结构的初始化,可以调用pthread_attr_destroy函数。如果pthread_attr_init实现时为属性对象分配了动态内存空间,pthread_attr_destroy还会用无效的值初始化属性对象,因此如果经pthread_attr_destroy去除初始化之后的pthread_attr_t结构被pthread_create函数调用,将会导致其返回错误。
线程属性结构如下:
typedef struct
{
int detachstate; 线程的分离状态
int schedpolicy; 线程调度策略
structsched_param schedparam; 线程的调度参数
int inheritsched; 线程的继承性
int scope; 线程的作用域
size_t guardsize; 线程栈末尾的警戒缓冲区大小
int stackaddr_set;
void* stackaddr; 线程栈的位置
size_t stacksize; 线程栈的大小
}pthread_attr_t;
每个个属性都对应一些函数对其查看或修改。下面我们分别介绍。
大致步骤为:
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setXXX(&attr,
目标值);
……//创建线程,其他代码
pthread_attr_destroy(&attr);
通过一系列的set函数设置pthread_attr_t类型结构体attr的值。
1.线程分离状态
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int*detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *attr, intdetachstate);
设置线程的分离状态为PTHREAD_CREATE_JOINABLE或PTHREAD_CREATE_DETACHED。
默认是joinable,有一些资源会在线程结束后仍然保持占用状态,直到另外的线程对这个线程使用pthread_join。detached线程不是这样子的,它没有被其他的线程所等待(join),自己运行结束了,线程也就终止了,马上释放系统资源。
若成功返回0,若失败返回-1。
2.线程的调度策略
int pthread_attr_getschedpolicy(const pthread_attr_t *restrict attr,
int *restrict policy);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
设置调度策略为SCHED_OTHER、SCHED_FIFO、SCHED_RR。默认调度为other。
若成功返回0,若失败返回-1。
3.线程的调度参数
int pthread_attr_getschedparam(const pthread_attr_t *restrict attr,
struct sched_param *restrictparam);
int pthread_attr_setschedparam(pthread_attr_t *restrict attr,
const struct sched_param*restrict param);
结构param的子成员__sched_priority控制一个优先权值,大的优先权值对应高的优先权。
若成功返回0,若失败返回-1。
4.线程的继承调度
int pthread_attr_getinheritsched(constpthread_attr_t *restrict attr,
int*restrict inheritsched);
int pthread_attr_setinheritsched(pthread_attr_t*attr, int inheritsched);
设置线程是否继承父线程的调度,即此线程的调度策略及优先级是继承于父线程,还是通过set设定两个属性。值为:PTHREAD_INHERIT_SCHED,PTHREAD_EXPLICIT_SCHED。
默认是inherit继承父线程的。
若成功返回0,若失败返回-1。
5.线程的竞争范围
int pthread_attr_getscope(const pthread_attr_t *restrict attr,
int *restrict contentionscope);
int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope);
定义创建的线程的竞争范围为PTHREAD_SCOPE_SYSTEM、PTHREAD_SCOPE_PROCESS。
Linux Threads只实现了PTHREAD_SCOPE_SYSTEM,这意味着,它将和机器上运行的所有进程竞争CPU时间。
标准指定的另外一个值,PTHREAD_SCOPE_PROCESS,表示竞争只存在于运行中的进程的线程之间:即,线程的优先级是相对于其它进程中的线程的优先级的,而不必考虑进程的优先级如何。LinuxThread不支持PTHREAD_SCOPE_PROCESS。
若成功返回0,若失败返回-1。
6.线程的栈的地址和大小
(1)
int pthread_attr_getstack(pthread_attr_t *attr,void **stackaddr,size_t*stacksize);
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,size_t stacksize);
设置线程栈的起始地址和栈大小。默认起始地址0,大小0x800000(8M,我的机子……)。
PS:使用get时往往显示的是addr
= 0,size = 0,这可能是系统的BUG,size应给为8M而不是0。
(2)
上面的2个函数可以细化成4个:
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);
int pthread_attr_getstackaddr(pthread_attr_t *attr, void**stackaddr);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_tstacksize);
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t*stacksize);
这里get得到的size为8M,所以pthread_attr_getstack获得的size大小是不能说明栈的大小的。
7.栈溢出保护区大小
intpthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
intpthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);
设置线程的栈溢出保护区大小,默认4096B,即4K。
8.
设置/获取线程属性对象里CPU
姻亲属性
int pthread_attr_setaffinity_np(pthread_attr_t *attr,size_tcpusetsize,
const cpu_set_t *cpuset);
int pthread_attr_getaffinity_np(pthread_attr_t *attr, size_tcpusetsize,
cpu_set_t *cpuset);
函数把 attr
引用的线程属性对象中的 CPU
姻亲掩码设置为cpuset
指定的值。这个属性决定了使用线程属性对象 attr
创建的线程的 CPU
姻亲掩码。
举例说明:
int anyka_pthread_create(pthread_t *thread_id, anyka_thread_main *func, void *arg, int stack_size, int priority)
{
int ret;
pthread_attr_t SchedAttr;
struct sched_param SchedParam;
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
//anyka_print("pthread priority(SCHED_RR)=(min=%d,max=%d)\n", sched_get_priority_min(SCHED_RR), sched_get_priority_max(SCHED_RR));
//anyka_print("pthread priority(SCHED_FIFO)=(min=%d,max=%d)\n", sched_get_priority_min(SCHED_FIFO), sched_get_priority_max(SCHED_FIFO));
#endif
/** init sched param attribute **/
pthread_attr_init(&SchedAttr);
if(priority != -1)
{
ret = pthread_attr_setinheritsched(&SchedAttr, PTHREAD_EXPLICIT_SCHED);
if (ret != 0)
anyka_print("pthread_attr_setschedpolicy, %s\n", strerror(ret));
ret = pthread_attr_setschedpolicy(&SchedAttr, SCHED_RR);
if (ret != 0)
anyka_print("pthread_attr_setschedpolicy, %s\n", strerror(ret));
SchedParam.sched_priority = priority;
ret = pthread_attr_setschedparam(&SchedAttr, &SchedParam);
if (ret != 0)
anyka_print("pthread_attr_setschedparam, %s\n", strerror(ret));
}
ret = pthread_attr_setstacksize(&SchedAttr, stack_size);
if (ret != 0)
anyka_print("pthread_attr_setstacksize, %s\n", strerror(ret));
ret = pthread_create(thread_id, &SchedAttr, func, arg);
if(ret != 0)
anyka_print("pthread_create [ %x ] failed, %s\n", (unsigned int)*func, strerror(ret));
pthread_attr_destroy(&SchedAttr);
return ret;
}
#include <string.h>
#include<pthread.h>
#include<sched.h>
void *child_thread(void *arg)
{
int policy = 0;
int max_priority = 0,min_priority = 0;
struct sched_param param;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED);
pthread_attr_getinheritsched(&attr,&policy);
if(policy == PTHREAD_EXPLICIT_SCHED){
printf("Inheritsched:PTHREAD_EXPLICIT_SCHED\n");
}
if(policy == PTHREAD_INHERIT_SCHED){
printf("Inheritsched:PTHREAD_INHERIT_SCHED\n");
}
pthread_attr_setschedpolicy(&attr,SCHED_RR);
pthread_attr_getschedpolicy(&attr,&policy);
if(policy == SCHED_FIFO){
printf("Schedpolicy:SCHED_FIFO\n");
}
if(policy == SCHED_RR){
printf("Schedpolicy:SCHED_RR\n");
}
if(policy == SCHED_OTHER){
printf("Schedpolicy:SCHED_OTHER\n");
}
max_priority = sched_get_priority_max(policy);
min_priority = sched_get_priority_min(policy);
printf("Maxpriority:%u\n",max_priority);
printf("Minpriority:%u\n",min_priority);
param.sched_priority = max_priority;
pthread_attr_setschedparam(&attr,¶m);
printf("sched_priority:%u\n",param.sched_priority);
pthread_attr_destroy(&attr);
}
int main(int argc,char *argv[])
{
pthread_t child_thread_id;
pthread_create(&child_thread_id, NULL, child_thread,NULL);
pthread_join(child_thread_id, NULL);
}
==[23]==gaoke@dev64_23:~/code$g++ -o test gaoke.cpp -lpthread
==[23]==gaoke@dev64_23:~/code$./test
Inheritsched:PTHREAD_EXPLICIT_SCHED
Schedpolicy:SCHED_RR
Maxpriority:99
Minpriority:1
sched_priority:99
相关文章推荐
- Linux下多线程编程__线程的创建pthread_create与退出pthread_exit,等待当前线程退出pthread_join,获取线程ID pthread_self
- clone的fork与pthread_create创建线程有何不同&pthread多线程编程的学习小结
- 多线程函数系列pthread_create(), pthread_join(), pthread_self(),pthread_exit(), pthread_detach()实例详解
- codeblocks 多线程编程时:对pthread_create未定义的引用
- 多线程编程实例---pthread_join函数详解1
- codeblocks 多线程编程时出现:对pthread_create未定义的引用,解决方法
- codeblocks 多线程编程时出现:对pthread_create未定义的引用,解决方法
- posix多线程有感--线程高级编程(线程属性pthread_attr_t)---实时调度
- linux下编译多线程程序, undefined reference to `pthread_create',undefined reference to `pthread_join'
- codeblocks 多线程编程时出现:对pthread_create未定义的引用,解决方法
- posix多线程有感--线程高级编程(线程属性pthread_attr_t)
- posix多线程有感--线程高级编程(线程属性pthread_attr_t)---实时调度
- 多线程编程实例---pthread_join函数详解1
- 多线程编程实例---pthread_join函数详解
- posix多线程有感--线程高级编程(线程属性pthread_attr_t)
- posix多线程有感--线程高级编程(线程属性pthread_attr_t)---实时调度
- 多线程--pthread_create, pthread_join
- posix多线程有感--线程高级编程(线程属性pthread_attr_t)
- LInux多线程编程----线程属性pthread_attr_t
- clone的fork与pthread_create创建线程有何不同&pthread多线程编程的学习小结