当前位置: 首页 > news >正文

线程(一) linux

目录

线程概念

资源划分

共享资源与私有资源

私有

共享

优缺点

优点

缺点

linux下的线程

LWP(轻量级进程 Light Weight Progress)

线程控制

线程创建

线程等待

线程退出

获取线程ID

线程分离

简单封装

小知识


线程概念

进程:承担分配系统资源的实体


线程:操作系统调度的基本单位,是进程内部的执行流

不同的线程会被分配去执行不同的函数,作为一个进程内部的多个执行流

资源划分

函数可以看做虚拟地址的集合,不同的线程执行不同的函数相当于拥有不同的虚拟地址资源

共享资源与私有资源

私有

1.线程ID

2.线程的上下文数据

3.栈

4.errno

5.信号屏蔽字

6.调度优先级

共享

1.因为线程在同一地址空间中,所以全局资源(全局函数,全局变量)都是共享的,这里会出现可重入函数的问题

2.文件描述符表

3.信号处理方式

4.当前工作目录

5.用户id和组id

优缺点

优点

1.创建线程比创建进程代价小

2.与进程切换相比,线程切换工作少

因为:

(1).线程切换时,无需切换CR3(CR3中存进程的页目录表基地址)

(2).TLB(缓存) 缓存的数据在线程切换时无需变化,进程切换时要更新

(3).线程切换时cache缓存不用更新,进程切换要更新

 

3.占用资源比进程少

4.能充分利用多处理器的可并行数量

5.在等待IO操作结束的时候,程序可以执行其他任务

6.对于计算密集型应用,可以将计算分解到多个线程中来在多处理器上并行

7.IO密集型应用,线程可以同时等待不同的IO操作,将IO操作重叠来提高性能

缺点

1.太多线程导致性能损失

2.健壮性降低,一个线程出问题,整个进程出问题

3.缺乏访问控制

进程是访问控制的基本单位,一个线程调用某些OS函数会对整个进程造成影响

linux下的线程

1.linux中,内核中,线程的实现是用进程模拟的,复用了进程代码和结构

2.线程在进程的虚拟地址空间中运行,不同的线程访问虚拟地址空间中的一部分资源,通过不同线程执行不同的入口函数实现

LWP(轻量级进程 Light Weight Progress)

linux通过轻量级进程来模拟线程,就是在内核级,linux使用轻量级进程作为线程,只提供轻量级进程的系统调用

而为了适应环境(大多数人都使用线程,而不熟悉轻量级进程),通过外部库封装了一个原生线程库pthread

线程控制

注意:1.使用线程控制函数要引入<pthread.h>头文件

2.链接时要链接pthread库,加' -lpthread'选项

线程创建

pthread_create

thread:输出型参数,线程id  一个无符号长整数(unsigned long int) ,实际上是pthread线程库维护的线程结构体对象的起始地址

attr:线程属性,一般传nullptr即可

start routine:该线程执行的函数

arg:传递给该线程的参数,也就是给函数的参数


返回值 :成功返回0,失败返回错误码


线程中可以创建线程,这个新线程也是由进程创建的


ps -aL  查看进程

线程等待

pthread_join

thread: 线程id,就是pthread库中表明线程控制块的起始地址

retval :输出参数,获取新线程退出信息,不关心传nullptr即可


返回值 :成功返回0,失败返回错误码


join会阻塞等待线程执行完毕,主线程最后退出,自动解决子线程僵尸问题

线程退出

四种方式

1.exit 直接终止进程


2.线程函数return


3.pthread_exit  将使用此函数的线程退出

retval :输出参数,获取新线程退出信息,不关心传nullptr即可


4.pthread_cancel   会将指定线程退出

thread: 线程id,就是pthread库中表明线程控制块的起始地址

获取线程ID

pthread_self

线程分离

分离线程:如果不关心线程的返回值,那么使用这个告诉系统,线程退出时,自动释放资源,无需join

默认情况下,新创建的线程是joinable的,线程退出后,需要进行pthread_jioin操作,否则无法释放资源,导致资源泄露


1.如果让子线程自己去分离,因为主线程和多个子线程执行先后不确定,所以要让想办法子线程先执行

2.如果让主线程去分离,在适当位置分离即可

简单封装

#pragma once

#include <iostream>

#include <thread>

#include <functional>

#include <string>

#include <unistd.h>

#include <sys/syscall.h>

#define get_lwp_id() syscall(SYS_gettid)

using func_t = std::function<void()>;

const std::string threadname = "name";

class Thread

{

    bool _running;

    pthread_t _tid;

    pid_t _lwpid;

    std::string _name;

    func_t _func;

public:

    Thread(func_t func,const std::string &name = threadname)    

        :_name(name)

        ,_func(func)

        ,_running(false)

        {}

    ~Thread(){}    

    static void *start_routine(void *args)

    {

        Thread *self = static_cast<Thread*>(args);

        self->_running = true;

        self->_lwpid = get_lwp_id();

        self->_func();

        pthread_exit((void*)0);

    }

    void start()

    {

        int tmp = pthread_create(&_tid,nullptr,start_routine,this);

        if(tmp==0) {std::cout<<"pthread_start success"<<std::endl;}

    }

     

    void Join()

    {

        if(!_running) return;

        int tmp = pthread_join(_tid,nullptr);

        if(tmp==0) {std::cout<<"pthread_join success"<<std::endl;}

    }

};

使用举例

#include "thread.hpp"

#include <vector>

#include <iostream>

void test()

{

    for(int i=0;i<5;i++)

    {

        std::cout<<"runing......"<<std::endl;

        sleep(0.5);

    }

}

int main()

{

    std::vector<Thread> threads;

    for(int i=0;i<5;i++)

    {

        std::string name = "thread-";

        name += std::to_string(i+1);

        Thread t(test,name);

        threads.push_back(t);

    }

    for(int i=0;i<5;i++)

    {

        threads[i].start();

    }

    for(int i=0;i<5;i++)

    {

        threads[i].Join();

    }

    return 0;

}

小知识

1.windows中的线程专门定义了线程结构体及其调度算法

2.多个子线程执行先后顺序不定

3.linux线程库叫做用户级线程,因为使用的是用户级别的pthread库

 

4.主线程使用进程的栈(主线程的栈),子线程使用库内维护的开的新栈,子线程的栈是固定大小的,不会向下增长

5.线程管理不是进程为单位的(每个进程管着自己的线程),是全部系统中的lwp都由pthread库来管理

6.__thread 变量    编译器提供的编译修饰符(内置选项)

将变量声明为子线程自己的变量, 只支持内置类型


文章转载自:
http://braider.bdypl.cn
http://astylar.bdypl.cn
http://adios.bdypl.cn
http://butane.bdypl.cn
http://cabtrack.bdypl.cn
http://backplane.bdypl.cn
http://barbarously.bdypl.cn
http://cayuse.bdypl.cn
http://adoration.bdypl.cn
http://choli.bdypl.cn
http://bundestag.bdypl.cn
http://bothnia.bdypl.cn
http://aperiodic.bdypl.cn
http://aare.bdypl.cn
http://bug.bdypl.cn
http://argenteous.bdypl.cn
http://adjunctive.bdypl.cn
http://arthroscope.bdypl.cn
http://chlorodyne.bdypl.cn
http://ameloblast.bdypl.cn
http://canadien.bdypl.cn
http://astasia.bdypl.cn
http://bctv.bdypl.cn
http://algebrist.bdypl.cn
http://babs.bdypl.cn
http://cavalier.bdypl.cn
http://adfreeze.bdypl.cn
http://alphabet.bdypl.cn
http://argand.bdypl.cn
http://animateur.bdypl.cn
http://www.dtcms.com/a/281348.html

相关文章:

  • 前端医疗生命体征
  • MIPI DSI(四) video 和 command 模式
  • 比较vue和react框架
  • Windows 下 Visual Studio 开发 C++ 项目的部署流程
  • Spring Boot 启动原理揭秘:从 main 方法到自动装配
  • 判断QMetaObject::invokeMethod()里的函数是否调用成功
  • Process Lasso:提升电脑性能的得力助手
  • C++20 协程参考手册详解 - 源自 cppreference.com
  • Expression 类的静态方法
  • PostgreSQL 大数据量(超过50GB)导出方案
  • 国产化Excel处理组件Spire.XLS教程:在 C# 中生成 Excel文件
  • 关于LM74700-Q1低IQ理想二极管的应用与参数极限
  • saltstack安装部署
  • 对象数组列表转成树形结构--树形结构转成列表(处理菜单)
  • ORA-06413: 连接未打开
  • 设计网站集:经济信息数据 统计数据 + 农业 + 金属 + 药品 + 电子 + 加密货币 + 债券 + 期货 + 其他
  • 构建企业级项目管理全面数字化运营体系︱易趋(蓝云软件)总裁唐智勇
  • 东鹏饮料牵手盈飞无限质量管理系统(QMS)
  • 多方学习与安全多方计算
  • 电动汽车制动系统及其工作原理
  • 梁的振动特征函数分析
  • 算法学习笔记(1):组合数
  • 论文 视黄素与细胞修复
  • 可下载或通过爬虫获取疾病相关数据的网站及平台,涵盖临床数据、基因关联、药品信息等方向,并附注数据特点与获取方式:(不公开)
  • PHP安全漏洞深度解析:文件包含与SSRF攻击的攻防实战
  • keeplived双击热备配置
  • chrome浏览器(chrome138.0.0.0 )无法安装扩展程序,因为它使用了不受支持的清单版本解决方案
  • GAMES101 lec2-数学基础1(线性代数)
  • 03 51单片机之独立按键控制LED状态
  • HCIA第三次综合实验:VLAN