线程是cpu的调度单位,不拥有系统资源,和属于同一进程的其他线程共享进程的资源。
一、线程标识
进程id在整个系统中是唯一的,但线程id不同,只在它所属的进程环境中有效。
进程id用pid_t数据类型来表示,是一个非负整数,线程id用pthread_t数据类型来表示,实现的时候可以用一个结构来代表pthread_t数据类型。因此必须使用函数来对两个线程id进行比较。
#include <pthread.h> int pthread_equal(pthread_t tid1,pthread_t tid2); //返回值:若相等则返回非0值,否则返回0
线程可以通过调用pthread_self函数获得自身的线程id
#include <pthread.h> pthread_t pthread_self(void);
二、线程创建
调用pthread_create函数创建新线程
#include <pthread.h> int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr,void *(*start_rtn)(void*),void *restrict arg);
当pthread_create成功返回(返回0)时,由tidp指向的内存单元被设置为新创建线程的线程id。attr参数用于定制各种不同的线程属性,NULL代表默认属性的线程。
新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。
线程创建时并不能保证哪个线程会先运行:是新创建的线程或调用线程。
#include <stdio.h> #include <pthread.h> pthread_t ntid; void printids(const char *s) { pid_t pid; pthread_t tid; pid=getpid(); tid=pthread_self(); printf("%s pid %u tid %u ",s,(unsigned int)pid,(unsigned int)tid); } void *thr_fn(void *arg) { printids("new thread:"); return ((void *)0); } int main(void) { int err; err=pthread_create(&ntid,NULL,thr_fn,NULL); printids("main thread:"); sleep(1); exit(0); }
输出:
main thread: pid 4014 tid 3075741376
new thread: pid 4014 tid 3075738432
上述代码中,主线程需要休眠,如果主线程不休眠,它就可能退出,这样在新线程有机会运行之前整个进程就已经停止了。
新线程不能安全地使用ntid,如果新线程在主线程调用pthread_create返回之前就运行了,那么新线程看到的是未经初始化的ntid内容。
三、线程终止
单个线程在不终止整个进程的情况下停止它的控制流:
1)线程只是从启动例程中返回,返回值是线程的退出码
2)线程可以被同一进程中的其他线程取消
3)线程调用pthread_exit
#include <pthread.h> void pthread_exit(void *rval_ptr)
rval_ptr包含线程的退出状态,其他线程可以通过调用pthread_join函数访问到这个指针。
#include <pthread.h> int pthread_join(pthread_t thread,void **rval_ptr) //返回值:若成功则返回0,否则返回错误编号
#include <apue.h> #include <pthread.h> void *thr_fn1(void *arg) { printf("thread 1 returning "); return((void *)1); } void *thr_fn2(void *arg) { printf("thread 2 exiting "); pthread_exit((void *)2); } int main() { pthread_t tid1,tid2; void *tret; pthread_create(&tid1,NULL,thr_fn1,NULL); pthread_create(&tid2,NULL,thr_fn2,NULL); pthread_join(tid1,&tret); printf("thread 1 exit code %d ",(int)tret); pthread_join(tid2,&tret); printf("thread 2 exit code %d ",(int)tret); exit(0); }
当一个线程通过调用pthread_exit退出或者简单地从启动例程中返回时,进程中的其他线程可以通过调用pthread_join函数获得该线程的退出状态