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;
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值