由于pthread库不是Linux系统默认的库,连接时需要使用库实打实的libpthread.a,需在编译时加-lpthread参数
pthread_create
原型:int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,(void*)(*start_rtn)(void*),void *arg)
用法:#include
功能:pthread_create是类Unix操作系统(Unix、Linux、Mac OS X等)的创建线程的函数
说明:函数若线程创建成功,则返回0,若线程创建失败,则返回出错编号。返回成功时,由tidp指向的内存单元被设置为新创建线程的线程ID,attr参数用于指定各种不同的线程属性,新创建的线程从start_rtn函数的地址开始运行,该函数只有一个万能指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg的参数传入。
pthread_create()中的attr参数是一个结构指针,结构中的元素分别对应着新线程的运行属性,主要包括以下几项:
__detachstate,表示新线程是否与进程中其他线程脱离同步,如果置位则新线程不能用pthread_join()来同步,且在退出时自行释放所占用的资源。缺省为PTHREAD_CREATE_JOINABLE状态。这个属性也可以在线程创建并运行以后用pthread_detach()来设置,而一旦设置为PTHREAD_CREATE_DETACH状态(不论是创建时设置还是运行时设置)则不能再恢复到 PTHREAD_CREATE_JOINABLE状态。
__schedpolicy,表示新线程的调度策略,主要包括SCHED_OTHER(正常、非实时)、SCHED_RR(实时、轮转法)和 SCHED_FIFO(实时、先入先出)三种,缺省为SCHED_OTHER,后两种调度策略仅对超级用户有效。运行时可以用过 pthread_setschedparam()来改变。
__schedparam,一个struct sched_param结构,目前仅有一个sched_priority整型变量表示线程的运行优先级。这个参数仅当调度策略为实时(即SCHED_RR 或SCHED_FIFO)时才有效,并可以在运行时通过pthread_setschedparam()函数来改变,缺省为0。
__inheritsched,有两种值可供选择:PTHREAD_EXPLICIT_SCHED和PTHREAD_INHERIT_SCHED,前者表示新线程使用显式指定调度策略和调度参数(即attr中的值),而后者表示继承调用者线程的值。缺省为PTHREAD_EXPLICIT_SCHED。__scope,表示线程间竞争CPU的范围,也就是说线程优先级的有效范围。POSIX的标准中定义了两个值: PTHREAD_SCOPE_SYSTEM和PTHREAD_SCOPE_PROCESS,前者表示与系统中所有线程一起竞争CPU时间,后者表示仅与同进程中的线程竞争CPU。目前LinuxThreads仅实现了PTHREAD_SCOPE_SYSTEM一值。
pthread_attr_t结构中还有一些值,但不使用pthread_create()来设置。为了设置这些属性,POSIX定义了一系列属性设置函数,包括pthread_attr_init()、pthread_attr_destroy()和与各个属性相关的pthread_attr_get---/pthread_attr_set---函数。
范例:
点击(此处)折叠或打开
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 8
void *PrintHello(void *args)
{
int thread_arg;
sleep(1);
thread_arg = (int)args;
printf(&quot;Hello from thread %d\n&quot;, thread_arg);
return NULL;
}
int main(void)
{
int rc,t;
pthread_t thread[NUM_THREADS];
for( t = 0; t < NUM_THREADS; t++)
{
printf(&quot;Creating thread %d\n&quot;, t);
rc = pthread_create(&thread[t], NULL, PrintHello, (void *)t);
if (rc)
{
printf(&quot;ERROR; return code is %d\n&quot;, rc);
return EXIT_FAILURE;
}
}
for( t = 0; t < NUM_THREADS; t++)
pthread_join(thread[t], NULL);
return EXIT_SUCCESS;
}
pthread_join
原型: int pthread_join(pthread_t thread, void **retval)
用法:#include
功能:pthread_join()函数,以阻塞的方式等待thread指定的线程结束
说明:当函数返回时,被等待线程的资源被收回。如果进程已经结束,那么该函数会立即返回。并且thread指定的线程必须是joinable的。参数含义如下:thread: 线程标识符,即线程ID,标识唯一线程,retval: 用户定义的指针,用来存储被等待线程的返回值,成功时返回0, 失败时返回的则是错误号。
代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。
范例:
// 子线程阻塞,等待信号,然后输出字符串
// 主线程从键盘录入字符,给子线程发信号。
点击(此处)折叠或打开
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<pthread.h>
#include<time.h>
pthread_t tid;
sigset_t set;
void myfunc()
{
printf(&quot;hello\n&quot;);
}
static void* mythread(void*p)
{
int signum;
while(1){
sigwait(&set,&signum);
if(SIGUSR1==signum)
myfunc();
if(SIGUSR2==signum)
{
printf(&quot;Iwillsleep2secondandexit\n&quot;);
sleep(2);
break;
}
}
}
int main()
{
char tmp;
void*status;
sigemptyset(&set);
sigaddset(&set,SIGUSR1);
sigaddset(&set,SIGUSR2);
sigprocmask(SIG_SETMASK,&set,NULL);
pthread_create(&tid,NULL,mythread,NULL);
while(1)
{
printf(&quot;:&quot;);
scanf(&quot;%c&quot;,&tmp);
if('a'==tmp)
{
pthread_kill(tid,SIGUSR1);//发送SIGUSR1,打印字符串。
}
elseif('q'==tmp)
{
//发出SIGUSR2信号,让线程退出,如果发送SIGKILL,线程将直接退出。
pthread_kill(tid,SIGUSR2);
//等待线程tid执行完毕,这里阻塞。
pthread_join(tid,&status);
printf(&quot;finish\n&quot;);
break;
}
else
continue;
}
return 0;
}
pthread_self
原型:pthread_t pthread_self(void)
用法:#include
功能:获取当前调用线程的 thread identifier(标识号)
说明:pthread_t的类型为unsigned long int,所以在打印的时候要使用%lu方式,否则将产生神奇的结果。
范例:
点击(此处)折叠或打开
#include <pthread.h>
#include <stdio.h>
int main()
{
pid_t pid;
pthread_t tid;
pid = getpid();
tid = pthread_self();
/* tid是unsigned long int,这里只是方便转换 */
printf(&quot;pid %u tid %u (0x%x)\n&quot;, (unsigned int)pid,(unsigned int)tid, (unsigned int)tid);
return 0;
}
pthread_exit
原型:void pthread_exit(void *retval)
用法:#include
功能:使用函数pthread_exit退出线程,这是线程的主动行为;由于一个进程中的多个线程是共享数据段的,因此通常在线程退出之后,退出线程所占用的资源并不会随着线程的终止而得到释放,但是可以用pthread_join()函数来同步并释放资源。
说明:retval:pthread_exit()调用线程的返回值,可由其他函数如pthread_join来检索获取。
范例:
点击(此处)折叠或打开
#include <stdio.h>
#include <pthread.h>
/*thread 1*/
void thread_1(void)
{
int i=0;
for(i=0;i<=6;i++)
{
printf(&quot;This is a pthread_1.\n&quot;);
if(i==2)
pthread_exit(0); //用pthread_exit()来调用线程的返回值,用来退出线程,但是退出线程所占用的资源不会随着线程的终止而得到释放
sleep(1);
}
}
/*thread 2*/
void thread_2(void)
{
int i;
for(i=0;i<3;i++)
printf(&quot;This is a pthread_2.\n&quot;);
pthread_exit(0);//用pthread_exit()来调用线程的返回值,用来退出线程,但是退出线程所占用的资源不会随着线程的终止而得到释放
}
int main(void)
{
pthread_t id_1,id_2;
int i,ret;
/*创建thread 1*/
ret=pthread_create(&id_1,NULL,(void *) thread_1,NULL);
if(ret!=0)
{
printf(&quot;Create pthread error!\n&quot;);
return -1;
}
/*创建thread 2*/
ret=pthread_create(&id_2,NULL,(void *) thread_2,NULL);
if(ret!=0)
{
printf(&quot;Create pthread error!\n&quot;);
return -1;
}
/*等待线程结束*/
pthread_join(id_1,NULL);
pthread_join(id_2,NULL);
return 0;
} |