> 文章列表 > 10、操作系统——线程的相关属性(2)

10、操作系统——线程的相关属性(2)

10、操作系统——线程的相关属性(2)

目录

一、线程调度

1、三种调度算法

(1)SCHED_FIFO(先进先出的排队方式调度)

(2)SCHED_RR实时调度策略,时间片轮转

(3)SCHED_OTHER 分时调度策略(linux默认)

 2、pthread_attr_setschedpolicy/pthread_attr_getschedpolicy(获取、设置线程的调度策略)

 二、线程栈合警戒

1、pthread_attr_setstacksize/pthread_attr_getstacksize(获取、设置线程栈大小、警戒区大小)

 2、各个线程相对独立的栈

三、线程退出

1、pthread_exit(线程自己退出)​编辑

         2、pthread_cancel(线程取消)(请线程退出)

3、创建一个线程,在1s后发送取消线程的请求,线程终止

一、线程调度

1、三种调度算法

(1)SCHED_FIFO(先进先出的排队方式调度)

静态优先级设置为1-99,则线程如果处于就绪态,就能立即抢占静态优先级为0的普通线程。

a、就绪态时,放入优先级队列的队尾位置

b、被更高优先级的线程抢占之后,会被放入优先级队列的队头位置,当所有优先级比他高的线程不再运行后,就恢复运行

c、调用sched_yield()后,会被在优先级队列的队尾位置

总结:该线程会一直运行直到发送I/O请求,或者被更高优先级线程抢占,或者调用sched_yield()主动让出CPU

(2)SCHED_RR实时调度策略,时间片轮转

与SCHED_FIFO类似,区别在于设置了时间片,当时间片耗光时,会被在优先级队列的队尾位置,可以用sched_rr_get_interval( )来获得时间片的具体数值。

(3)SCHED_OTHER 分时调度策略(linux默认)

静态优先级必须设置为0

处于 0 优先级别的这些线程按照所谓的动态优先级被调度,而动态优先级起始于线程的 nice 值,且每当一个线程已处于就绪 态但被调度器调度无视时,其动态优先级会自动增加一个单位,这样能保证这些线程竞争 CPU 的公平性。

 2、pthread_attr_setschedpolicy/pthread_attr_getschedpolicy(获取、设置线程的调度策略)

 二、线程栈合警戒区

1、pthread_attr_setstacksize/pthread_attr_getstacksize(获取、设置线程栈大小、警戒区大小)

 2、各个线程相对独立的栈

线程的栈可能溢出,需要增大栈空间,因为有警戒区,故不需要这么做,警戒区是没有任何访问权限的内存,用来保护相邻的两条线程的栈空间不被彼此践踏。

三、线程退出

1、pthread_exit(线程自己退出)

 2、pthread_cancel(线程取消)(请线程退出)

 某个时刻不能等某个线程“自然死亡”(例如在while(1)中),需要令其马上结束,可以给线程发送一个取消请求,让其中断执行退出。

而当线程收到一个取消请求时,他将会如何表现取决于两个东西:

一是当前的取消状态:

         PTHREAD_CANCEL_ENABLE 使能 (允许取消。默认值)         PTHREAD_CANCEL_DISABLE 失能 (不允许取消)

二是当前的取消类型:

        延时响应 等待线程遇到取消点时响应取消的请求

        立即响应

3、创建一个线程,在1s后发送取消线程的请求,线程终止

#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>void * func (void * arg)
{int * p = calloc(1,4);while(1){printf("这里是func线程,线程ID :%ld \\n" , pthread_self() );sleep(1);}*p = 1024 ;// 退出本线程并设置返回值的地址(返回了num 的地址)pthread_exit((void *)p); //返回的内存地址应该时一个堆空间
}int main(int argc, char const *argv[])
{// 创建线程pthread_t t_id  = -1 ;pthread_create( &t_id , //新线程ID号NULL , // 线程属性, NULL 默认属性func,  // 线程需要执行的例程(新线程需要执行的任务《函数》) NULL ); // 线程的参数printf("t_id : %ld\\n" , t_id) ;printf("这里是主函数,线程ID :%ld \\n" , pthread_self() );int * retval ;int ret_val = 0 ;sleep(1);pthread_cancel( t_id );// 阻塞等待接合线程printf("等待 function 线程退出:\\n");if( ret_val = pthread_join( t_id , (void*)&retval)){fprintf(stderr , "接合失败:%s\\n" , strerror(ret_val));}printf("结合线程成功, 退出值为:%d\\n" , *retval);// 尝试接合线程  (非阻塞)// int ret_val = 0 ;// if( ret_val = pthread_tryjoin_np( t_id , (void*)&retval))// {//     fprintf(stderr , "接合失败:%s\\n" , strerror(ret_val));// }return 0;
}

上述例子可以取消线程,但是没办法结合线程的退出值

旅游攻略