线程控制

news2024/11/25 6:58:43

对线程的控制思路和进程相似,创建、等待、终止,只需要调用接口就行。但是在Linux下没有线程的概念,因为Linux的设计者认为,线程是一种轻量级的进程,毕竟创建线程只需要创建PCB。因此Linux中使用多线程必须使用第三方pthread库,线程库为用户提供接口。


线程的创建——pthread_create

参数:

tread是线程标识符的指针,类似进程pid

attr是线程属性,一般是nullptr

start_routine是线程执行的函数

arg是传递给线程函数的参数

返回值:


线程的终止

线程终止有三种方式:

1.线程函数执行return,就会结束进程

2.线程函数使用pthread_exit接口

3.一个线程中使用pthread_cancel接口终止另一个进程 


线程的等待——pthread_join

 

参数:

 thread是线程标识符

retval是标识符对应线程退出后的返回值,是一个输出型参数。因为线程函数的返回值是void*类型,所以参数类型必须是void**


分离线程——pthread_detach

如果说线程的返回值我们不关心,使用join对操作系统是一种负担,但是不等待线程也会造成内存泄漏。使用这个接口就不用等待线程,在线程执行完自动回收。

分离线程既可以在其他线程分离,也可以自己分离

其他线程传入要分离的线程ID,自己分离调用pthread_self()获取线程tid即可


进程控制的例子:

#include <iostream>
#include <pthread.h>
#include <string>
#include <unistd.h>
using namespace std;
//使用线程实现从a到b的累加
class Request
{
public:
    int _start;
    int _end;
    string _threadname;

    Request(int start, int end, string name)
    :_start(start)
    ,_end(end)
    ,_threadname(name)
    {}
};

class Response
{
public:
    int _val;
    int _exitcode;

    Response(int val, int exitcode)
    :_val(val)
    ,_exitcode(exitcode)
    {}
};

void* cal(void* arg)
{
    Request* rq = (Request*)arg;
    Response* rsp = new Response(0, 0);
    for(int i = rq->_start; i <= rq->_end; i++)
    {
        usleep(100000);
        rsp->_val += i;
        cout << rq->_threadname << " pid:" << getpid() << " operate" <<": ret += " << i << endl;
    }
    //线程间共用堆,把主线程的数据释放
    delete rq;
    return rsp;
}

int main()
{
    pthread_t tid;
    Request* rq = new Request(0,50,"mythread");
    //创建线程
    cout << "main thread pid:" << getpid() << " create thread" << endl;
    pthread_create(&tid, nullptr, cal, (void*)rq);
    void* ret;
    //等待线程,获取结果
    pthread_join(tid, &ret);
    Response* rsp = (Response*)ret;
    cout << rq->_threadname <<" cal ret = " << rsp->_val << " exitcode = " << rsp->_exitcode << endl; 
    delete rsp;
    return 0;
}

使用线程库,编译时要用-lpthread选项,声明使用的库
通过指令看到线程的PID相同,因为它们都是同一个进程的执行流资源,LWP是线程标识符,不同线程互不相同


线程ID

我们知道LInux系统没有线程概念,线程这个概念是由线程库来维护的,线程库调用了系统调用接口clone

 clone是创建进程的接口(fork的底层也使用了它),线程库对其封装,提供可以创建线程的接口。那么,线程库必然会对建立的所有线程进行管理,就像操作系统管理进程一样,创建对应的TCB等等。

线程库是一个动态库,进程运行时会加载到共享区。库中就有线程对应的数据结构,这些数据结构都被存储到一个数组中,数组中每个线程的数据结构的地址就是它的tid

从上面的动态库结构看到:线程有自己独立的栈和局部存储


线程栈

独立性

线程栈相互独立,也就是说每个线程即使使用了相同的线程函数,创建的变量也是互不相同的。

#include <iostream>
#include <pthread.h>
#include <vector>

#define NUM 4//线程数量
using namespace std;

void* fun(void* arg)
{
    int val = 10;
    return (void*)&val;//返回栈中变量地址
}

int main()
{   
    vector<pthread_t> tids;
    //创建多个线程
    for(int i = 0; i < NUM; i++)
    {
        pthread_t tid;
        pthread_create(&tid, nullptr, fun, nullptr);
        tids.push_back(tid);
    }
    //查看栈中变量地址
    for(auto e : tids)
    {
        void* ret;
        pthread_join(e, &ret);
        cout << (int*)ret << endl;
    }
    return 0;
}

可见性

虽然栈是相互独立的,但是并不意味着栈中的数据对其他线程是不可访问的(实际应用中不推荐这种访问)

#include <iostream>
#include <pthread.h>
#include <vector>
#include <unistd.h>
using namespace std;
int* addr;
void* fun(void* arg)
{
    int val = 0;
    addr = &val;
    int cnt = 10;
    //循环打印val
    while(cnt--)
    {
        sleep(1);
        cout << "val:" << val <<endl;
    }
    return nullptr;
}
int main()
{
    //创建线程
    pthread_t tid;
    pthread_create(&tid, nullptr, fun, nullptr);
    //修改val
    sleep(4);
    cout << "main change val: 10" << endl;
    *addr = 10;
    pthread_join(tid, nullptr);
    return 0;
}


线程局部存储

一个进程的全局变量对所有的线程都是可见的,如果想要一个线程独有的全局变量,可以使用线程局部存储。

在全局变量定义的前面加上 __thread

#include <iostream>
#include <pthread.h>
#include <vector>
#include <unistd.h>

using namespace std;
__thread int gval = 0;

void *fun1(void *arg)
{
    gval += 100;
    cout << &gval << ' ' << gval << endl;
    return nullptr;
}

void *fun2(void *arg)
{
    gval += 200;
    cout << &gval << ' ' << gval << endl;
    return nullptr;
}
int main()
{
    vector<pthread_t> tids;
    pthread_t tid;
    pthread_create(&tid, nullptr, fun1, nullptr);
    tids.push_back(tid);
    pthread_create(&tid, nullptr, fun2, nullptr);
    tids.push_back(tid);

    for (auto e : tids)
    {
        pthread_join(e, nullptr);
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1930423.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

打破平台限制,使智能手机和平板电脑上无缝运行Windows x86/x64架构的软件和游戏的一款安卓应用

大家好&#xff0c;今天给大家分享一款专为Android设备设计的模拟器应用Winlator。其核心功能是能够在基于ARM架构的智能手机和平板电脑上无缝运行Windows x86/x64架构的软件和游戏。 Winlator是一款Android应用程序&#xff0c;它允许用户使用Wine和Box86/Box64在Android设备上…

Ubuntu的磁盘扩容遇到的问题

1.先用终端上的命令查看磁盘的使用情况 #查看磁盘空间容量的占用情况 $ df -h #查看当前文件夹中&#xff0c;各个文件占用磁盘空间的情况 $ du -sh* 如果容量少的话&#xff0c;需要尽快扩容 2.开机前的扩容 2.1 VMware 扩展磁盘空间 关闭当前客户机&#xff0c;在编辑虚拟…

《企业实战分享 · Druid 连接监控》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; 近期刚转战 CSDN&#xff0c;会严格把控文章质量&#xff0c;绝不滥竽充数&#xff0c;如需交流&#xff…

华为以客户为中心的战略

2005年&#xff0c;伴随着国际化步伐的加快&#xff0c;华为重新梳理了自己的愿景、使命和发展战略&#xff0c;提出了以客户为中心的战略定位&#xff1a; 为客户服务是华为存在的唯一理由&#xff1b;客户需求是华为发展的原动力。质量好、服务好、运作成本低&#xff0c;优…

部署kafkamanager

1&#xff0c;检查kafka的版本 到lib下查看 libs/kafka-clients-0.11.0.3.jar kafka的版本 0.11 2&#xff0c;下载kafkamanager 链接&#xff1a; https://pan.baidu.com/s/1qYifoa4 密码&#xff1a;el4o 3&#xff0c;解压后更改该conf下conf/application.conf 中zkhosts …

VUE:跨域配置代理服务器

//在vite.config。js中&#xff0c;同插件配置同级进行配置server:{proxy:{"/myrequest":{//代理域名&#xff0c;可自行修改target:"https://m.wzj.com/",//访问服务器的目标域名changeOrigin:true,//允许跨域configure:(proxy,options) > {proxy.on(&…

Ubuntu上安装配置samba服务

Ubuntu上安装配置samba服务 在Ubuntu中安装配置samba共享服务&#xff0c;可以让你在网络上共享文件和打印机。以下是一个相对详细的步骤指南&#xff0c;介绍如何在Ubuntu上安装和配置Samba。 1. 安装Samba 首先&#xff0c;需要安装Samba软件包。打开终端并运行以下命令&a…

【学习笔记】无人机系统(UAS)的连接、识别和跟踪(一)-3GPP TS 23.256 技术规范概述

3GPP TS 23.256 技术规范&#xff0c;主要定义了3GPP系统对无人机&#xff08;UAV&#xff09;的连接性、身份识别、跟踪及A2X&#xff08;Aircraft-to-Everything&#xff09;服务的支持。 3GPP TS 23.256 技术规范&#xff1a; 以下是文档的核心内容总结&#xff1a; UAV系…

设计模式-概述*

1.代码的质量的评判 可维护性&#xff1a;不破坏原有代码设计以及不引入新的bug的前提下&#xff0c;能够快速修改或新增代码&#xff1b;可读性&#xff1a;人类能理解的代码&#xff08;编程规范-命名、函数是否冗长、类是否过大等&#xff09;&#xff1b;可扩展性&#xff…

BiliBili 阴阳师主题 前端技术展示

实现效果 实现方式 纯 Html CSS 文件展示如下 下载地址 https://download.csdn.net/download/qq_43638033/89543490 部分代码解析 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"> <!-- 设置文档的字符编码…

【概率论三】参数估计

文章目录 一. 点估计1. 矩估计法2. 极大似然法1. 似然函数2. 极大似然估计 3. 评价估计量的标准2.1. 无偏性2.2. 有效性2.3. 一致性 三. 区间估计1. 区间估计的概念2. 正态总体参数的区间估计 参数估计讲什么 由样本来确定未知参数参数估计分为点估计与区间估计 一. 点估计 所…

每日刷题(cf)

目录 1.C. Increasing Sequence with Fixed OR 2.C. Jellyfish and Green Apple 3.B. Jellyfish and Game 1.C. Increasing Sequence with Fixed OR Problem - C - Codeforces 题目要求我们构造一个最长的序列&#xff0c;使得任意相邻两个元素按位或等于n&#xff0c;我们对…

汇智知了堂推出“鸿蒙系统开发培训”,探索万物互联新纪元

在数字化转型的浪潮中&#xff0c;操作系统作为连接硬件与软件的桥梁&#xff0c;其重要性不言而喻。随着5G、物联网、人工智能(AI)等技术的飞速发展&#xff0c;我们正步入一个万物皆可互联的时代。在这个背景下&#xff0c;华为推出的鸿蒙系统(HarmonyOS)应运而生&#xff0c…

【C语言习题】41.序列中删除指定数字

文章目录 题目代码 题目 代码 #include<stdio.h> int main() {int i,j;int n;int arr_1[100];int arr_2[100];int del;scanf("%d",&n);for(i0;i<n;i){scanf("%d",&arr_1[i]);}scanf("%d",&del);for(i0,j0;i<n;i){if(de…

【Linux】进程信号 --- 信号产生

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

【安全】系统安全设计规范(DOC完整版)

1.1安全建设原则 1.2 安全管理体系 1.3 安全管理规范 1.4 数据安全保障措施 1.4.1 数据库安全保障 1.4.2 操作系统安全保障 1.4.3 病毒防治 1.5安全保障措施 1.5.1实名认证保障 1.5.2 接口安全保障 1.5.3 加密传输保障 1.5.4终端安全保障 软件资料清单列表部分文档&…

旅游数据可视化:免费工具让复杂数据变得简单易懂

随着旅游业的蓬勃发展&#xff0c;海量的数据如同繁星点点&#xff0c;记录着每一位旅者的足迹与偏好。然而&#xff0c;如何将这些复杂的数据转化为直观、易懂的信息&#xff0c;为旅游企业精准决策、为消费者提供更加个性化的服务&#xff0c;成为了行业内外共同关注的焦点。…

Maven学习—如何在IDEA中配置Maven?又如何创建Maven工程?(详细攻略)

目录 前言 1.在IDEA中配置Maven 2.创建Maven项目 &#xff08;1&#xff09;Maven&#xff1a;创建普通Maven工程 &#xff08;2&#xff09;Maven Archetype&#xff1a;创建Maven模板工程 前言 本篇博客将详细的介绍在IDEA中如何配置Maven&#xff0c;以及如何创建一个Ma…

HMI 7寸 带壳 linux 系统的移植

问题&#xff1a; 目前的源码中 只有 android 的config 文件&#xff0c;需要再移植一个 Linux 的config 文件。 过程&#xff1a; 1 首先是可以正常启动。 首先将 4418 的config 文件拷贝到 HMI的源码中&#xff0c;编译一遍看看能不能正常编译正常启动。 cp xxxx .confi…

uniapp实现微信一键登录按钮样式,如何开发胶囊按钮的样式

效果图&#xff1a; 关键点&#xff1a;让圆角的值变成高度的一半。 核心样式&#xff1a; .content .btn{width: 600rpx;border-radius: 300rpx;background-color: rgb(62,204,97);color: white;font-weight: 500;}完整代码&#xff1a; <template><view class&q…