Linux线程

Linux线程

线程的概念

什么是线程

LWP: light weight process轻量级的进程,本质仍是进程(在Linux环境下)

进程: 独立地址空间,拥有PCB.

线程:也有PCB,但没有独立的地址空间(共享).

区别:在于是否共享地址空间。 独居(进程);合租(线程)。

Linux下:

  • 线程:最小的执行单位
  • 进程:最小分配资源单位,可看成是只有一个线程的进程。

Linux内核线程实现原理

类Unix系统中,早期是没有“线程”概念的, 80年代才引入,借助进程机制实现出了线程的概念。因此在这类系统中,进程和线程关系密切。

  1. 轻量级进程(light-weight process),也有PCB,创建线程使用的底层函数和进程一样,都是clone.
  2. 从内核里看进程和线程是一样的,都有各自不同的PCB.
  3. 进程至少有一个线程.
  4. 线程可看做奇存器和栈的集合.
  5. 在linux下,线程最是小的执行单位; 进程是最小的分配资源单位.

查看LWP号 : ps -Lf pid 查看指定线程的lwp号.

线程共享资源

  1. 文件描述符表
  2. 每种信号的处理方式 — 不建议信号与线程一起使用 太乱
  3. 当前工作目录
  4. 用户ID和组ID
  5. 内存地址空间 (text, data, bss, heap, 共享库)

线程非共享资源

  1. 线程 id
  2. 处理器现场和栈指针 (内核栈)
  3. 独立的栈空间 (用户空间栈)
  4. error变量
  5. 信号屏蔽字
  6. 调度优先等级

线程优缺点

优点 :

  • 提高程序并发性
  • 开销小
  • 数据通信,共享数据方便

缺点 :

  • 库函数不稳定
  • 调试编写困难
  • 对信号支持不好

优点行对突出, 缺点不是硬伤. Linux下由于实现方法导致进程 线程的差别不是很大.

线程相关函数

pthread_create 创建线程

#include <pthread.h>

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

参数

  • thread 传出参数线程ID
  • attr 线程属性,大多不使用
  • 第三参数 函数指针
  • arg 线程执行函数的参数

返回值

成功返回0 失败返回error

编译时需要加pthread库

gcc -o $@ $< -g -lpthread

pthread_self 得到线程号

#include <pthread.h>

pthread_t pthread_self(void);

例子

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>

void* thr(void *atg)
{
    printf("我是线程 我的pid = %d, tid = %lu\n",getpid(),pthread_self());
    
    return NULL;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid,NULL,thr,NULL);
    printf("我是主线程 pid = %d tid = %lu\n",getpid(),pthread_self());

    sleep(1);
    
    return 0;
}

pthread_exit 退出一个线程

#include <pthread.h>

void pthread_exit(void *retval);

例子 :

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

void *thr(void * val)
{
    printf("我是子线程pid = %d tid = %lu \n",getpid(),pthread_self());
    //return NULL;
    pthread_exit(NULL);
}

int main()
{
    pthread_t tid;
    pthread_create(&tid,NULL,thr,NULL);
    
    printf("我是主线程pid = %d tid = %lu \n",getpid(),pthread_self());
    
    pthread_exit(NULL);

    return 0;
}

注意事项:

  • 在线程中使用pthread_exit
  • 在线程中使用return (主控进程代表退出进程)
  • exit代表退出整个进程

pthread_join 获取线程返回值 回收线程

#include <pthread.h>

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

参数

  • thread 创建时候传入的第一个参数
  • retval 传出线程的退出信息

例子 :

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

void *thr(void * val)
{
    printf("我是子线程 tid = %lu\n",pthread_self());
    sleep(4);
    printf("我是子线程 tid = %lu\n",pthread_self());
    return (void*)20;

}

int main()
{
    pthread_t tid;
    pthread_create(&tid,NULL,thr,NULL);

    printf("我是主线程 tid = %lu\n",pthread_self());
    
    void *ret;
    pthread_join(tid,&ret); // 线程回收, 线程未执行完 阻塞

    printf("子线程返回值:%d\n",((int)ret));
    
    pthread_exit(NULL);
    return 0;
}

pthread_cancel 杀死线程

#include <pthread.h>

int pthread_cancel(pthread_t thread);

例子 :

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

void *thr(void *val)
{
        while(1)
        {
                printf("我是子线程,tid = %d\n",pthread_self());
                sleep(1);
        }
        pthread_exit(NULL);
}

int main()
{
        pthread_t tid;
        pthread_create(&tid,NULL,thr,NULL);
        
        sleep(5);
        pthread_cancel(tid);
        void *ret;
        pthread_join(tid,&ret);

        printf("返回值:%d\n",(int)ret);

        return 0;
}

pthread_detach 实现线程分离

线程分离状态:指定该状态,线程主动与主控线程断开关系。线程结束后,其退出状态不由其他线程获取,而直接自己自动释放。网络、多线程服务器常用.

进程若有该机制,将不会产生僵尸进程。僵尸进程的产生主要由于进程死后,大部分资源被释放,一点残留资源仍存于系统中,导致内核认为该进程仍存在.

也可使用pthread_create函数参2(线程属性)来设置线程分离.

不需要使用pthread_join回收资源.

#include <pthread.h>

int pthread_detach(pthread_t thread);

例子 :

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


void *thr(void *arg)
{
        
        printf("我是线程 tid = %lu\n",pthread_self());
        sleep(4);
        printf("我是线程 tid = %lu\n",pthread_self());
        //pthread_exit(NULL);
        return 0;
}

int main(int argc, char *argv[])
{
        pthread_t tid;
        pthread_create(&tid,NULL,thr,NULL);

        pthread_detach(tid);
        sleep(5);
        int ret = pthread_join(tid,NULL);
        if(ret > 0){
                printf("join error:%d, %s\n",ret,strerror(ret));
        }
        return 0;
}

运行结果 :

我是线程 tid = 139732708251392
我是线程 tid = 139732708251392
join error:22, Invalid argument

pthread_equal 判断两个线程是否相等

#include <pthread.h>

int pthread_equal(pthread_t t1, pthread_t t2);

线程id在进程内是唯一的, 但是在系统中不是唯一的.

查看线程库版本

getconf GNU_LIBPTHREAD_VERSION

创建多少线程合适?

cpu核数*2 + 2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

去留意

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值