POSIX线程(POSIX threads),简称Pthreads,是线程的POSIX标准。该标准定义了创建和操纵线程的一整套API。POSIX线程具有很好的可移植性,使用pthreads编写的代码可运行于Solaris、FreeBSD、Linux 等平台,Windows平台亦有pthreads-win32可供使用。
Pthreads定义了一套C语言的类型、函数与常量,它以pthread.h头文件和一个线程库实现。
一、 创建和终止线程
#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); void pthread_exit(void *retval); int pthread_cancel(pthread_t thread);
pthread_create功能是创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数。
pthread_create的返回值:表示成功,返回0;表示出错,返回-1。
thread:指向线程标识符的指针
attr:用来设置线程属性,可以指定线程属性对象,或者为默认值指定NULL
start_routine:线程运行函数的起始地址
arg:运行函数的参数,如果不传递参数,则可以使用NULL
二、 Joining and Detaching线程
pthread_detach()和pthread_join()就是控制子线程回收资源的两种不同的方式。同一进程间的线程具有共享和独立的资源,其中共享的资源有堆、全局变量、静态变量、文件等公用资源。而独享的资源有栈和寄存器,这两种方式就是决定子线程结束时如何回收独享的资源。
pthread_detach()即主线程与子线程分离,两者相互不干涉,子线程结束同时子线程的资源自动回收。pthread_join()即是子线程合入主线程,主线程会一直阻塞,直到子线程执行结束,然后回收子线程资源,并继续执行。
#include <pthread.h> int pthread_join(pthread_t thread, void **retval); int pthread_detach(pthread_t thread);
#include <stdio.h> #include <pthread.h> #define NUM_THREADS 10 void *sayhello(void *tid) { int threadno = *(int *)tid; printf("Hello, thread: %d\n", threadno); pthread_exit(NULL); } int main(void) { pthread_t threads[NUM_THREADS]; int threadno[NUM_THREADS], retval; for(int i=0; i<NUM_THREADS; i++) { printf("Creating thread: %d\n", i); threadno[i] = i; retval = pthread_create(&threads[i], NULL, sayhello, (void *)&threadno[i]); if(retval != 0) { printf("pthread_create error\n"); return 1; } } for(int i=0; i<NUM_THREADS; i++) { retval = pthread_join(threads[i], NULL); if(retval != 0) { printf("pthread_join error\n"); return 1; } } pthread_exit(NULL); return 0; }
[ycxie@fedora Workspace]$ gcc pthreaddemo.c -o pthreaddemo -pthread [ycxie@fedora Workspace]$ ./pthreaddemo Creating thread: 0 Creating thread: 1 Creating thread: 2 Hello, thread: 1 Creating thread: 3 Hello, thread: 2 Creating thread: 4 Hello, thread: 3 Hello, thread: 0 Creating thread: 5 Hello, thread: 4 Creating thread: 6 Hello, thread: 5 Creating thread: 7 Hello, thread: 6 Hello, thread: 7 Creating thread: 8 Creating thread: 9 Hello, thread: 8 Hello, thread: 9
三、 参数传递
#include <stdio.h> #include <string.h> #include <pthread.h> #define NUM_THREADS 5 struct student { int id; char name[100]; char addr[100]; }; void *sayhello(void *arg) { struct student *p = (struct student *)arg; printf("%d\t%s\t%s\n", p->id, p->name, p->addr); pthread_exit(NULL); } int main(void) { pthread_t threads[NUM_THREADS]; struct student data[NUM_THREADS]; int retval; data[0].id = 0; strcpy(data[0].name, "Xie Yincai"); strcpy(data[0].addr, "Beijing China"); data[1].id = 1; strcpy(data[1].name, "Barack Obama"); strcpy(data[1].addr, "United States of America"); data[2].id = 2; strcpy(data[2].name, "Dennis Ritchie"); strcpy(data[2].addr, "United States of America"); data[3].id = 3; strcpy(data[3].name, "Donald Trump"); strcpy(data[3].addr, "United States of America"); data[4].id = 4; strcpy(data[4].name, "Michael Jordan"); strcpy(data[4].addr, "United States of America"); for(int i=0; i<NUM_THREADS; i++) { printf("Creating thread: %d\n", i); retval = pthread_create(&threads[i], NULL, sayhello, (void *)&data[i]); if(retval != 0) { printf("pthread_create error\n"); return 1; } } for(int i=0; i<NUM_THREADS; i++) { retval = pthread_join(threads[i], NULL); if(retval != 0) { printf("pthread_join error\n"); return 1; } } pthread_exit(NULL); return 0; }
[ycxie@fedora Workspace]$ ./pthreaddemo Creating thread: 0 Creating thread: 1 0 Xie Yincai Beijing China 1 Barack Obama United States of America Creating thread: 2 Creating thread: 3 2 Dennis Ritchie United States of America Creating thread: 4 3 Donald Trump United States of America 4 Michael Jordan United States of America