线程(thread)----轻量级的进程、CPU调度的最小单位,相比较于进程,进程是分配资源的最小单位。
之前讲到的是多进程编程,这一部分要说的是如何在一个进程中实现多线程编程(当然将进程部分的内容放到一起,就可以实现多进程多线程编程)。POSIX(可移植性操作系统接口)规定了可移植性的线程库pthread库<pthread.h>,这里面的函数需要在编译时加上-lpthread(-pthread)参数,pthread库中的类型以及函数是不透明的(掌握如何使用,无须关心如何实现)。
一个进程中至少有一个线程,从main()开始运行的线程称为 主线程(初始线程)。线程id类型pthread_t,可以使用pthread_self()返回,需要注意的是,线程id只是在一个进程内有效(进程id在整个系统中有效);使用pthread_equal()比较两个线程的id是否相等。
- pthread_t pthread_self(void);
- int pthread_equal(pthread_t tid1, pthread_t tid2);
- int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, void *(*start_rtn)(void*), void *arg);
1.受OS调度影响,被创建的线程处于就绪状态,故创建线程的线程往往是先被调用。
2.同一进程中的多个线程共享内存资源,故多个线程对进程中的所有变量都是共享的(但要注意该变量的生存期和作用域)。
3.只要进程(主线程)退出,其余未结束的线程都随之结束了(进程结束资源也就没了)
4.同一进程中的多个线程共享文件描述符,并非复制一份。
5.同一进程中的多个线程共享进程的信号屏蔽字,但新线程的未决信号集讲被清空。
进程退出的方式:从start_rtn返回;自身调用pthread_exit()函数;被同一个进程中的其他线程取消。先来看pthread_exit()函数和与之配套的pthread_join()函数:
- void pthread_exit(void *rval_ptr);
- int pthread_join(pthread_t thread, void **rval_ptr);
线程中也有类似进程atexit()注册清理操作的函数,pthread_cleanup_push() pthread_cleanup_pop()注册线程的清理函数。
- void pthread_cleanup_push(void (*rtn)(void *), void *arg);
- void pthread_cleanup_pop(int execute);
再来说下pthread_cancel()函数,它和pthread_exit()都能使一个线程退出,不同是后者是使线程本身退出,而前者是使同一进程中的其他线程退出。
- int pthread_cancel(pthread_t tid);
- void pthread_testcancel(void);
- int pthread_setcancelstate(int state, int *oldstate);
- int pthread_setcanceltype(int type, int *oldtype);
再介绍一下其他的线程属性,线程属性的类型是pthread_attr_t类型,类型的初始化和销毁分别是pthread_attr_init() pthread_attr_destroy()两个函数:
- int pthread_attr_init(pthread_attr_t *attr);
- int pthread_attr_destroy(pthread_attr_t *attr);
- int pthread_detach(pthread_t tid);
- int pthread_attr_getdetachstate(const pthread_attr_t * attr, int *detachstate);
- int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
pthread_detach()函数使tid线程分离,后面两个函数操作的是线程属性的结构,detachstate的值可以是PTHREAD_CREATE_JOINABLE不分离(默认的) PTHREAD_CREATE_DETACHED分离。这两种方法的区别是,第一种用于线程已被创建后分离,另一种用于创建前设置。