线程

线程概念

在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”。这里的内部是指指向同一个地址空间。一切进程至少都有一个执行线程。

进程和线程

  • 进程是系统分配资源竞争的基本单位。
  • 线程是程序执行的最小单位。
  • 线程共享进程数据,但也拥有自己的一部分数据:线程ID,一组寄存器,栈,errno,信号屏蔽字,调度优先级。
    同一地址空间,因此Text Segment,Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程都可以访问到,除此之外,各线程还共享以下进程资源和环境:

  • 文件描述符表,代码和数据共享

  • 每种信号的处理方式(Hander表共享)
  • 当前工作目录
  • 用户id和组id

区别与关联

  • 线程比进程更细致(粒度细), 线程是在进程内部的执行流。
  • Linux下没有真正的线程,都是用进程模拟线程的。Linux下的线程被成为轻量级进程(成本低)。
  • 线程是调度的基本单位,每个线程都有独立的上下文,用来切换。有独立的栈结构,用来保存临时数据。
  • 进程:创建PCB,创建资源(地址空间,页表,物理内存)。

    线程的创建
    int pthread_create(pthread_t pthread,const pthread_attr_t *attr,void (start_routine)(void),void *arg);
    参数:thread:返回线程ID
    attr:设置线程的属性,attr为NULL表示使用默认属性
    start_routine:是个函数地址,线程启动后要执行的函数
    arg:传给线程启动的参数
    返回值:成功返回0,失败返回错误码
    代码:

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
void* rout(void* arg){
    int i;
    for( ; ; ){
        printf("I am thread 1\n");
        sleep(1);
    }
}
int main(void){
    pthread_t tid;
    int ret;
    if((ret = pthread_create(&tid,NULL,rout,NULL)) != 0){
        fprintf(stderr,"pthread_create: %s\n",strerror(ret));
        exit(EXIT_FAILURE);
    }
    int i;
    for(; ; ){
        printf("I am main thread\n");
        sleep(1);
        //两个死循环,两个执行流,新线程执行最上面的循环,主线程执行另外一个循环
    }
}

这里写图片描述

注意在写Makefile时要引入库
这里写图片描述
线程的等待
- 为什么会有线程等待?已经退出的线程,其空间没有被释放,仍然在进程的地址空间内。
- 创建新的进程不会复用刚才退出线程的地址空间。
原型:
int pthread_join(pthread_t thread,void **value_ptr);
参数:
thread:线程ID
value_ptr:它指向一个指针,后者指向线程的返回值。
返回值:
成功返回0,失败返回错误码
调用该函数的线程挂起等待,直到ID为thread的线程终止。thread线程以不同的方式终止,通过pthread_join 得到的终止状态是不同的,总结如下:
- 如果thread线程通过return返回,value_ptr所指的单元里存的是thread线程函数的返回值。
- 如果thread线程被别的线程调用pthread_cancel异常终止,value_ptr所指的单元里存放的是常数PTHREAD_CANCELED.
- 如果thread线程是自己调用pthreadexit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数。
- 如果对thread线程的终止状态不感兴趣,可以传NULL给value_ptr参数。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
void* thread1(void* arg){
    printf("thread 1 returning ...\n");
    int *p = (int*)malloc(sizeof(int));
    *p = 1;
    return (void*)p;
}

void* thread2(void* arg){
    printf("thread 2 returning ...\n");
    int *p = (int*)malloc(sizeof(int));
    *p = 2;
    pthread_exit((void*)p);
}
void* thread3(void* arg){
    while(1){
        printf("thread 3 returning ...\n");
        sleep(1);
    }
    return NULL;
}
int main(void){
    pthread_t tid;
    void *ret;

    //thread 1 return
    pthread_create(&tid,NULL,thread1,NULL);
    pthread_join(tid,&ret);
    printf("thread return,thread id %x,return code:%d\n",tid,*(int*)ret);
    free(ret);

    //thread 2 exit
    pthread_create(&tid,NULL,thread2,NULL);
    pthread_join(tid,&ret);
    printf("thread return,thread id %x,return code:%d\n",tid,*(int*)ret);
    free(ret);

    //thread 3 cancel by other
    pthread_create(&tid,NULL,thread3,NULL);
    sleep(3);
    pthread_cancel(tid);
    pthread_join(tid,&ret);
    if(ret == PTHREAD_CANCELED){
        printf("thread return,thread id %x,return code:PTHREAD_CANCELED\n",tid);
    }else{
        printf("thread return,thread id %x,return code:NULL\n",tid);
    }
}

这里写图片描述
线程的分离与结合

  • 默认情况下,新创建的线程是可结合的,线程退出后,需要对其进行等待操作,否则无法释放资源,从而造成系统泄露。
  • 如果不关心线程的返回值,等待是一种负担,这个时候,我们可以告诉系统,当线程退出时,自动释放线程资源。
    原型:
    int pthread_detach(pthread_t thread);
    可以是线程组内其他线程对目标线程进行分离,也可以是线程自己分离。
    pthread_detach(pthread_self());
    结合和分离是冲突的,一个线程不能即是结合的又是分离的。线程就算被分离,一旦出现异常,也会连累进程。
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
#include<string.h>
void* thread_run(void* arg){
    pthread_detach(pthread_self());
    printf("%s\n",(char*)arg);
    return NULL;
}
int main(){
    pthread_t tid;
    if( pthread_create(&tid,NULL,thread_run,"thread1 run...") != 0){
        printf("create thread error\n");
        return 1;
    }
    int ret = 0;
    sleep(1);
    if( pthread_join(tid,NULL) == 0){
        printf("pthread wait success\n");
        ret = 0;
    }else{
        printf("pthread wait failed\n");
        ret = 1;
    }
    return ret;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值