线程(Linux)

Thread
Thread application scenario

有些情况需要在一个进程中同时执行多个控制流程,这时候线程就派上了用用场,比如实现一个图形界面的下载软件,一方面需要和用户交互,等待和处理用户的鼠标键盘事件,另一方面又需要同时下载多个文件,等待和处理从多个网络主机发来的数据,这些任务都需要一个“等待-处理”的循环,可以用多线程实现,一个线程专门负责与用户交互,另外几个线程每个线程负责和一个网络主机通信。

main与Thread

main函数和信号处理函数是同一个进程地址空间中的多个控制流程,多线程也是如此,但是比信号处理函数更加灵活,信号处理函数的控制流程只是在信号递达时产生,在处理完信号之后就结束,而多线程的控制流程可以长期并存,操作系统会在各线程之间调度和切换,就像在多个进程之间调度和切换一样。

Linux中的thread和process
  • 进程是分配资源的基本实体
  • 线程是调度的基本单位
  • 进程强度资源独享,线程强调资源共享
  • Linux中没有真正意义上的线程,进程就是线程,用进程模拟线程
  • 线程是在进程的内部运行(在进程的地址空间运行)
Thread Shared

同一进程的多个线程共享同一地址空间,因此文本段、数据段都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到

  • 文件描述符表
  • 每种信号的处理方式(SIG_IGN、SIG_DFL或者自定义的信号处理函数)
  • 当前工作目录
  • 用户id和组id
Thread Private
  • 线程id(只在用户区有效)
  • 上下文(包括各种寄存器的值、程序计数器)
  • 栈结构
  • 栈空间
  • errno变量
  • 信号屏蔽字
  • 调度优先级
Thread Create

函数原型:
int pthread_create(pthread_t*thread,constpthread_attr_t attr, void(start_routine)(void ), void *arg);

  • pthread_t *thread:线程id
  • const pthread_attr_t *attr:线程属性,通常为NULL
  • void*(start_routine)(void ):线程调用的函数
  • void *arg:线程调用的函数的参数
void* thread_run(void* val)
{
    printf("newthread pid=%dtid=%lu\n",getpid(),pthread_self());
    return NULL;
    //pthread_self()->获得线程id
}
int main()
{
    pthread_t tid;//定义线程id
    int ret=pthread_create(&tid,NULL,thread_run,0);
    if(ret!=0)//判断是否创建成功
    {
        printf("%d->%s",ret,strerror(ret));
    }
    //strerror(3)->将错误码对应的错误信息打印
}
Thread Exit
  • 从线程函数return
  • 线程调用void pthread_exit(void *retval)函数终止自己
  • 一个线程调用函数int pthread_cancel(pthread_t thread)终止同一进程中的另一个线程
void* thread_run(void* val)
{
    printf("newthread pid=%d tid=%lu\n",getpid(),pthread_self());
    //return (void*)123;
    //return NULL;从线程函数return,对主线程不适用
    //exit(1);不能在线程内调用exit(),否则整个进程将终止
    //pthread_exit((void*)333);//调用pthread_exit(void*val)终止自己
    //pthread_cancel(pthread_self());//一般不这样终止
        while(1){
    printf("newthread pid=%d tid=%lu\n",getpid(),pthread_self());
    }//pthread_cancel(id)代码
}

int main()
{
    pthread_t id;
    int ret = pthread_create(&id,NULL,thread_run,0);
    if(ret!=0)
    {
        printf("%d->%s",ret,strerror(ret));
    }
    sleep(2);
    void* val = NULL;
    pthread_cancel(id);//一个线程调用该函数终止同一进程中的另一个线程,退出码为-1;
    pthread_join(id,&val);//线程等待
    printf("manthread  pid=%d tid= %lu exit= %d\n",getpid(),pthread_self(),(int)val);
    return 0;
}
Thread Wait

阻塞式等待,解决类似于进程僵死状态
函数原型:int pthread_join(pthread_t thread, void **retval);

  • pthread_t thread:线程id
  • void **retval:输出型参数,获取退出码
Thread joinable and deteached

一个可结合(joinable)的线程能够被其他线程收回资源并杀死,在被其他线程收回之前他的存储器(栈)是不释放的
一个可分离(deteached)的线程不能够被其他线程收回资源并杀死,它的存储器资源在它终止时由系统自动释放


  • 默认情况下,线程被创建成可结合的
  • 可结合的线程必须被显示回收(调用pthread_join),要么被分离(pthread_detach)
  • 如果调用pthread_join之后,线程还在运行,调用者阻塞

解决方法:

1.在子线程中加入代码
pthread_detach(pthread_self());
2.在主线程中加入代码
pthread_detach(tid);
//测试代码
void* thread_run(void* val)
{
    pthread_detach(pthread_self());//自己分离
    printf("newthread pid=%d tid=%lu\n",getpid(),pthread_self());
    return NULL;
}
int main()
{
    pthread_t id;
    int ret = pthread_create(&id,NULL,thread_run,0);
    if(ret!=0)
    {
        printf("%d->%s",ret,strerror(ret));
    }
    sleep(2);
    //void* val = NULL;
    if(pthread_join(id,NULL)==0)
    {
        printf("wait success! %d\n",ret);
    }else
    {
        printf("wait faild! %d\n",ret);
    }
//  printf("manthread  pid=%d tid= %lu exit= %d\n",getpid(),pthread_self(),(int)val);
    return 0;
}
Important error

这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值