线程的创建和回收

进程

  • 进程有独立的地址空间
  • Linux为每个进程创建task_struct
  • 每个进程都参与内核调度,互不影响

线程

  • 进程在切换时系统开销大
  • 很多操作系统引入了轻量级进程LWP
  • 同一进程中的线程共享相同地址空间
  • Linux不区分进程、线程

线程特点

  • 通常线程指的是共享相同地址空间的多个任务
  • 大大提高了任务切换的效率
  • 避免了额外的TLB & cache的刷新

线程共享资源

一个进程中的多个线程共享以下资源:

  • 可执行的指令
  • 静态数据
  • 进程中打开的文件描述符
  • 当前工作目录
  • 用户ID
  • 用户组ID

线程私有资源

每个线程私有的资源包括:

  • 线程ID (TID)
  • PC(程序计数器)和相关寄存器
  • 堆栈
  • 错误号 (errno)
  • 优先级
  • 执行状态和属性

Linux线程库

pthread线程库中提供了如下基本操作

  • 创建线程
  • 回收线程
  • 结束线程

同步和互斥机制

  • 信号量
  • 互斥锁

线程创建 – pthread_create

 #include  <pthread.h>  

int  pthread_create(pthread_t *thread, const  pthread_attr_t *attr, void *(*routine)(void *), void *arg);  

  • 成功返回0,失败时返回错误码  
  • thread 线程对象  
  • attr 线程属性,NULL代表默认属性  
  • routine 线程执行的函数  
  • arg 传递给routine的参数 ,参数是void * ,注意传递参数格式

线程结束 – pthread_exit

 #include  <pthread.h>

 void  pthread_exit(void *retval);          

  • 结束当前线程  
  • retval可被其他线程通过pthread_join获取  
  • 线程私有资源被释放

线程查看tid函数

pthread_t  pthread_self(void)   查看自己的TID

#include <pthread.h>

pthread_t pthread_self(void);

线程创建与结束代码范例

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void *testThread(void *arg){
    printf("This is a thread test,pid=%d,tid=%lu\n",getpid(),pthread_self());
   // return NULL;
    printf("input arg=%d\n",(int)arg);//可以打印出来
    pthread_exit(NULL);
    printf("after pthread exit\n");//打印不出来,线程已经退出
}
int main(){
    pthread_t tid;
    int ret;
    int arg = 5;
   
    ret = pthread_create(&tid,NULL,testThread,(void *)arg);

    printf("This is main thread,tid=%lu\n",tid);    
    sleep(1);
}

注意事项:

  • 1.主进程的退出,它创建的线程也会退出。
  • 2.线程创建需要时间,如果主进程马上退出,那线程不能得到执行

线程间参数传递

编译错误:

createP_t.c:8:34: warning: dereferencing ‘void *’ pointer printf("input arg=%d\n",(int)*arg);

createP_t.c:8:5: error: invalid use of void expression printf("input arg=%d\n",(int)*arg);

错误原因是void *类型指针不能直接用*取值(*arg),因为编译不知道数据类型。

解决方法:转换为指定的指针类型后再用*取值  比如:*(int *)arg

  1. 通过地址传递参数,注意类型的转换
  2. 值传递,这时候编译器会告警,需要程序员自己保证数据长度正确

线程回收 – pthread_join

 #include  <pthread.h>  

int  pthread_join(pthread_t thread, void **retval);    

对于一个默认属性的线程 A 来说,线程占用的资源并不会因为执行结束而得到释放  

  • 成功返回0,失败时返回错误码  
  • thread 要回收的线程对象  
  • 调用线程阻塞直到thread结束  
  • *retval 接收线程thread的返回值

线程回收代码实例

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *func(void *arg){
    printf("This is child thread\n");
    sleep(25);
    pthread_exit("thread return");

}


int main(){
    pthread_t tid[100];
    void *retv;
    int i;
    for(i=0;i<100;i++){
        pthread_create(&tid[i],NULL,func,NULL);
    }
    for(i=0;i<100;i++){
        pthread_join(tid[i],&retv);//阻塞,如果线程没有退出,则等待
        printf("thread ret=%s\n",(char*)retv);//返回的字符串是pthread_exit函数的参数
    }
    while(1){    
        sleep(1);
    } 

}

线程回收的其他方式,使用线程的分离:

两种方式:

1 使用pthread_detach

2 创建线程时候设置为分离属性

  pthread_attr_t attr;

  pthread_attr_init(&attr);

  pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

线程分离pthead_detach

int pthread_detach(pthread_t thread);    

成功:0;失败:错误号

指定该状态,线程主动与主控线程断开关系。线程结束后(不会产生僵尸线程)  
 

线程分离代码实例

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *func(void *arg){
    pthread_detach(pthread_self());//方法二
    printf("This is child thread\n");
    sleep(25);
    pthread_exit("thread return");

}


int main(){
    pthread_t tid[100];
    void *retv;
    int i;
    for(i=0;i<100;i++){
        pthread_create(&tid[i],NULL,func,NULL);
       // pthread_detach(tid);//方法一
    }
    
    while(1){    
        sleep(1);
    } 

}

设置线程属性为分离

pthread_attr_t attr;

pthread_attr_init(&attr);

pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

设置线程属性为分离实例

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *func(void *arg){
    printf("This is child thread\n");
    sleep(25);
    pthread_exit("thread return");

}


int main(){
    pthread_t tid[100];
    void *retv;
    int i;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

    for(i=0;i<100;i++){
        pthread_create(&tid[i],&attr,func,NULL);
    }
    
    while(1){    
        sleep(1);
    } 

}

取消一个线程

int pthread_cancel(pthread_t thread);     杀死一个线程

void pthread_testcancel(void);  

int pthread_setcancelstate(int state, int *oldstate);

PTHREAD_CANCEL_ENABLE

PTHREAD_CANCEL_DISABLE  

int pthread_setcanceltype(int type, int *oldtype);

PTHREAD_CANCEL_DEFERRED                

PTHREAD_CANCEL_ASYNCHRONOUS 

线程的清理

void pthread_cleanup_push(void (*routine) (void *), void *arg)

void pthread_cleanup_pop(int execute)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值