多线程编程时有以下几点需要特别关注:
- 创建线程时,仅仅申请线程自身的栈空间,与同进程的其他线程共享其他地址空间,包括代码段、数据段、堆等。
- 内核仍然把线程当做一个进程进行处理的,只不过不再分配内存而已
- 进程是操作系统管理资源的基本单元,线程时Linux系统调度的基本单元
1、创建线程
//from /usr/include/bits/pthread.h
int pthread_create(pthread_t* pid,pthread_attr_t* attr,
void*(fun)(void*),void* param);
函数第1个参数用来存储线程的ID,第2个参数为线程属性,一般置为NULL即可,第3个参数为线程执行的函数,第4个参数为函数的参数地址,如果需要传入多个参数,则可以使用结构体进行传递,函数执行成功返回0,否则返回-1。
2、线程退出
//from /usr/include/bits/pthreadtypes.h
void pthread_exit(void* status);
3、线程等待
int pthread_join(pthread_t pid,void** return);
int pthread_detach(pthread_t pid); //等待分离线程
函数第1个参数为线程ID,第2个参数为等待的线程返回的状态地址。函数执行成功返回0,否则阻塞。
4、设置线程被取消时的处理函数
void pthread_cleanup_push((void*)(func)(void*),void* arg);
void pthread_cleanup_pop(int flag);
为解决线程会不可预见的取消,导致某些临界资源未来的及释放,从而导致异常,因而引入资源自动释放概念。函数pthread_cleanup_push用来将函数func放入资源自动释放的处理函数栈中,而pthread_cleanup_pop则是从该栈中弹出,并根据flag值,决定是否执行该函数(1表示执行,0表示仅弹出),另外在线程中两个函数必须成对出现。
5、线程取消
int pthread_cancel(pthread_t pid);
函数用来向线程pid发送取消操作,实际上,该线程不一定会被取消,要根据线程状态决定。
6、设置线程状态是否可被取消
int pthread_setcancelstate(int state,int* oldstate);
函数第1个参数为设置的新状态值,oldstate用来存储老的状态值,函数执行成功返回0,否则返回-1。
新的状态值有以下两个选项:
- PTHREAD_CANCEL_DISABLE:线程的取消请求将处于未决状态,即现在不处理,等线程状态改变后,才会被取消。
- PTHREAD_CANCEL_ENABLE:创建线程的默认状态,线程的取消请求将被立即接受。
7、设置线程的取消类型
int pthread_setcanceltype(int state,int* oldstate);
函数有两个参数,state为新类型,oldstate存储原先的老类型。
即使线程的取消请求被接受,也会有两个类型,一个是立即接受(PTHREAD_CANCEL_ASYNCHRONOUS),一个是在取消点时才会接受(PTHREAD_CANCEL_DEFERRED),线程默认的取消类型。