5、线程(李慧琴课程笔记)
概念
一个正在运行的函数
POSIX线程是一套标准,而不是实现。
openmp线程(不太重要,了解即可)
线程表示 pthread_t
ps -ax -L以Linux形式查看进程和线程。PID为进程,LWP为轻量级进程,也就是线程。
**注意:**不能贸然打印pthread_t标识,可能会出错
int pthread_equal(pthread_t t1, pthread_t t2);/*比较两个线程标识,如果相等返回非0,反之返回0*/
pthread_t pthread_self(void);/*返回当前线程标识*/
5.1 sche_yield()函数的作用:
出让调度器
pthread_mutex_unlock(&mut_num);
sche_yield();/*出让调度器给别的线程,相当于别的线程也可以抢这个互斥所了*/
pthread_mutex_lock(&mut_num);
pthread_mutex_lock()函数不一定只能对应一个pthread_mutex_unlock()函数。
5.2 线程的创建
其实这里有个小技巧,如果说你想传入线程处理函数一个好看一点的不用强转的变量的话,可以考虑用结构体指针的形式,比如你定义一个*P的结构体,那么arg参数直接写P,然后在start_routine这个函数里面直接使用P->函数成员就行了
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);/*成功返回为0,失败返回error number*/
/*pthread_t *thread 这个是回填给你的线程标识,就是你先注册一个pthread_t 类型的线程标识,放到这,然后函数就会给你回填*/
/*const pthread_attr_t *attr 在获取线程标识的时候,给线程标识指定的属性,一般是写NULL,也就是默认属性*/
/*void *(*start_routine)(void *) 传入的函数指针*/
/*void *arg 传入第三个参数,也就是要传入函数的参数*/
线程的调度取决于调度器策略
5.3线程的终止和栈清理
线程终止三种方式
- 线程从启动例程返回,返回值就是线程的退出码
- 线程可以被同一进程中的其他线程取消
- 线程调用pthread_exit()函数
void pthread_exit(void *retval);/*retval返回值可以自己定,但肯定是一个指针*/
int pthread_join(pthread_t thread, void **retval);/*类似于wait()函数,注意thread是变量不是地址*/
/*void **retval若写空则是只收尸,不关心状态*/
栈的清理
void pthread_cleanup_push(void (*routine)(void*), void *arg);/*routine这儿是传入一个函数*/
/*pthread_cleanup_push是钩子函数*/
void pthread_cleanup_pop(int execute);/*当execute为0时只取栈,不调用具体函数*/
pthread_cleanup_push和pthread_cleanup_pop应该是成对出现的,两个其实都是宏定义,在我们预处理文件的时候就可以看出来
5.4线程的取消
int pthread_cancel(pthread_t thread);
线程取消:pthread_cancel
取消有两种状态:允许和不允许
允许取消又分为:异步cancel,推迟cancel(默认)->推迟至cancel点再响应
cancel点:POSIX定义的cancel点,都是可能引发阻塞的系统调用
int pthread_setcancelstate(int state, int *oldstate);/*设置是否允许取消*/
int pthread_setcanceltype(int type, int *oldtype);/*设置取消方式*/
void pthread_testcancel(void);/*本函数什么都不做,就是一个取消点*/
int pthread_detach(pthread_t thread);/*线程分离,就是把一个线程分离出去,不再理会*/
5.5 互斥量
关于互斥量的使用可以看一下李慧琴老师的视频,这里不多做解说了
注意:要注意临界区之内的跳转语句如:continue、break、go to、函数调用,要记得解锁再跳转到临界区外,同时还要注意,并不是说一个lock就只对应一个unclok,需要分情况讨论的。
int pthread_mutex_destory(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);/*mutex就是咱们的互斥量,attr则是索要的属性,后面会有相关的详细解释*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*静态初始化互斥量的方式,pthread_mutex_init则是动态初始化方式,动态可能就是位于结构体当中或者需要初始化属性之类的*/
int pthread_mutex_lock(pthread_mutex_t *mutex);/*阻塞的上锁*/
int pthread_mutex_trylock(pthread_mutex_t *mutex);/*非阻塞模式的上锁*/
int pthread_mutex_unlock(pthread_mutex_t *mutex);/*解锁用的*/