首页 > 系统相关 >【C++】Linux多线程开发

【C++】Linux多线程开发

时间:2024-03-24 16:29:21浏览次数:22  
标签:printf include int void Linux C++ 线程 pthread 多线程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


3.1线程概述

◼ 与进程(process)类似,线程(thread)是允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程。同一个程序中的所有线程均会独立执行相同程序,且共享同一份全局内存区域,其中包括初始化数据段、未初始化数据段,以及堆内存段。(传统意义上的 UNIX 进程只是多线程程序的一个特例,该进程只包含一个线程)
◼ 进程是 CPU 分配资源的最小单位,线程是操作系统调度执行的最小单位。
◼ 线程是轻量级的进程(LWP:Light Weight Process),在 Linux 环境下线程的本质仍是进程。
◼ 查看指定进程的 LWP 号:ps –Lf pid

提示:

◼ 进程间的信息难以共享。由于除去只读代码段外,父子进程并未共享内存,因此必须采用
一些进程间通信方式,在进程间进行信息交换。
◼ 调用 fork() 来创建进程的代价相对较高,即便利用写时复制技术,仍然需要复制诸如
内存页表和文件描述符表之类的多种进程属性,这意味着 fork() 调用在时间上的开销
依然不菲。
◼ 线程之间能够方便、快速地共享信息。只需将数据复制到共享(全局或堆)变量中即可。
◼ 创建线程比创建进程通常要快 10 倍甚至更多。线程间是共享虚拟地址空间的,无需采
用写时复制来复制内存,也无需复制页表。

◼ 共享资源
 进程 ID 和父进程 ID
 进程组 ID 和会话 ID
 用户 ID 和 用户组 ID
 文件描述符表
 信号处置
 文件系统的相关信息:文件权限掩码
(umask)、当前工作目录
 虚拟地址空间(除栈、.text)

◼ 非共享资源
 线程 ID
 信号掩码
 线程特有数据
 error 变量
 实时调度策略和优先级
 栈,本地变量和函数的调用链接信息


提示:以下是本篇文章正文内容,下面案例可供参考

3.2 创建线程

进程:计算机分配资源的最小单位
线程:计算机调度的最小单位

gcc pthread_exit.c -o exit -pthread //第三方库pthread
/*
    #include <pthread.h>

    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
            void *(*start_routine) (void *), void *arg);
        -功能:创建一个子线程;一般情况,main函数所在的线程称为主线程(main线程)
                其余创建的线程称为子线程
                程序中默认只有一个进程,fork()函数调用,2个进程
                程序中默认只有一个线程
        -参数:
            thread:传出参数,创建成功的子线程的ID
            attr:设置线程的属性,一般默认值,NULL
            start_routine:函数指针,子线程需要处理的逻辑代码
            arg:给第三个参数使用,传参数
        返回值:
            成功:0
            失败:返回错误号,这个错误号和之前errno不一样
            获取错误号信息:char*  strerror(int errnum) ;

*/
#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<unistd.h>
void *callback(void *arg){
   
    printf("childthread\n");
    printf("arg value:%d\n",*(int *)arg);
    return NULL;
}

int main(){
   
    pthread_t tid;
    int num =99;
    //创建一个子线程
    int ret=pthread_create(&tid,NULL,callback,(void*)&num);

    if(ret!=0){
   
        char *errstr = strerror(ret);
        printf("error:%s\n",errstr);
    }

    for(int j = 0; j < 10; j++) {
   
        printf("j = %d\n", j);
    sleep(1);
    }

    return 0; // exit(0);
}




3.3、线程终止

/*
    #include <pthread.h>
    void pthread_exit(void *retval);
        功能:终止一个线程,在哪个线程中调用,就表示终止哪个线程
        参数:
            retval:需要传递一个指针,作为一个返回值,可以在pthread_join()中获取
    
    pthread_t pthread_self(void);
        获取当前线程的线程ID

    int pthread_equal(pthread_t t1, pthread_t t2); // 跨平台使用
        比较两个线程ID是否相等
            不同的操作系统,pthread_t的类型不一样,
            有无符号long int, 也有结构体
*/
#include<stdio.h>
#include<pthread.h>
#include<string.h>
void *callback(void *arg){
   
    printf("childthread ID :%ld\n",pthread_self());
    return NULL;//pthread_exit(NULL);
}

int main(){
   
    pthread_t tid;

    //创建一个子线程
    int ret=pthread_create(&tid,NULL,callback,NULL);

    if(ret!=0){
   
        char *errstr = strerror(ret);
        printf("error:%s\n",errstr);
    }

    for(int j = 0; j < 1000; j++) {
   
        printf("j = %d\n", j);
    }

    printf("tid:%ld, mainthread ID :%ld\n",tid,pthread_self());
    
    //退出主线程,但是不会影响其他子线程的运行
    pthread_exit(NULL);

    printf("living?\n");//无法执行
    return 0;//exit(0);
}

3.4连接已经终止线程

/*
    #include <pthread.h>
    int pthread_join(pthread_t thread, void **retval);
        和已经终止的线程连接进行连接
            回收子线程的资源
            这个函数是阻塞函数,调用一次只能回收一个子线程
            一般在主线程中使用
        
        thread:需要回收的子线程的ID
        retval:接受子线程退出时的返回值

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


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

int value=10;
void *callback(void *arg){
   
    printf("childthread ID :%ld\n",pthread_self());
    sleep(3);
    //return NULL;//pthread_exit(NULL);
    //int value= 10; 不能返回局部变量,线程结束,栈空间释放,返回随机值
    pthread_exit((void *)&value);//return (void *)&value;
}

int main(){
   
    pthread_t tid;

    //创建一个子线程
    int ret=pthread_create(&tid,NULL,callback,NULL);

    if(ret!=0){
   
        char *errstr = strerror(ret);
        printf("error:%s\n",errstr);
    }

    for(int j = 0; j < 10; j++) {
   
        printf("j = %d\n", j);
    }

    printf("tid:%ld, mainthread ID :%ld\n",tid,pthread_self());
    
    //主线程调用pthread_join()回收子线程资源

    int *thread_retval;
    int re=pthread_join(tid,(void **)&thread_retval);
    //为什么传递二级指针,
    //对int变量的值操作时,要传入一级指针
    //而对int *进行操作,传入二级指针
    if(re!=0){
   
        char *errstr = strerror(ret);
        printf("error:%s\n",errstr);
    }

    printf("exit data:%d\n",*thread_retval);

    printf("回收子线程成功!\n");
    //退出主线程,但是不会影响其他子线程的运行
    pthread_exit(NULL);

    return 0;
}

3.5 线程的分离

/*
    #include <pthread.h>
    int pthread_detach(pthread_t thread);
        分离一个线程,被分离的线程在终止时,会自动释放资源返回系统
        1.不能多次分离,会产生不可预料的行为
        2.不能去连接一个已经分离的线程,会报错
        
        thread:需要分离的线程ID

        返回值:
            成功0;
            失败:返回错误号

*/
#include <pthread.h>
#include<stdio.h>
#include<string.h>
#inclu

标签:printf,include,int,void,Linux,C++,线程,pthread,多线程
From: https://blog.csdn.net/love_boke/article/details/136553947

相关文章

  • 【每周例题】力扣 c++ 自除数
    自除数题目 题目分析1.这道题可以直接用暴力求解,动用for循环遍历从left到right的每个数,使用while判断是否为自除数。2.满足自除数有两个要求:1.数位不能存在0;2.自除数除于数位为0;这里可以使用if语句进行判断。3.由于自除数的数量位置,所以存储自除数可以采用容器或者数列来存......
  • 【每周例题】力扣 c++ 各位相加
    各位相加题目各位相加 题目解析这个题目看似需要使用递归方法或者使用while循环进行求解,其实你只需要统计前三十个数就可以发现规律:  根据图表可知,除了数字0,其他数字各位相加的最后结果都是其数字对9取模。所以从这个结果可以得到以下代码代码#include<iostream>u......
  • Linux:网络套接字的认识和基本实现通信
    文章目录UDP和TCP协议网络字节序socket编程常见的接口套接字本篇总结的是对于网络套接字的基本认识UDP和TCP协议在谈网络套接字前,必须先对于UDP和TCP这两个协议有一个基本的认识,这两个协议都是隶属于传输层的协议,并且这两个协议距离用户来说是最近的,所以一般以数据......
  • 数据结构/C++:位图 & 布隆过滤器
    数据结构/C++:位图&布隆过滤器位图实现应用布隆过滤器实现应用哈希表通过映射关系,实现了O(1)的复杂度来查找数据。相比于其它数据结构,哈希在实践中是一个非常重要的思想,本博客将介绍哈希思想的两大应用,位图与布隆过滤器。位图看到以下题目:给40亿个无序不重......
  • C++创建异步任务
    namespaceCore{/***创建一个异步任务的包装函数,返回一个指向std::packaged_task的shared_ptr。**@tparamF函数类型*@tparamArgs参数类型*@paramf要执行的函数*@paramargs函数的......
  • Linux打包---Deb包安装和卸载
    包名规则:  package_version-revision_arch.deb dpkg安装信息查看参数:   #dpkg--debug=100:打印安装日志  #dpkg--log=filename:打印日志到文件  #dpkg-x或dpkg-X:将deb包内文件解压出来 安装过程目录/etc/dpkg/dpkg.cfg     ......
  • C++共享之道:用extern实现源文件变量与类成员函数的巧妙共享
    概述:在C++中,使用`extern`关键字可实现在源文件之间共享变量与类成员函数。通过声明变量或类在头文件中,再在一个源文件中定义,其他源文件通过`extern`引用,促使模块化、可维护的代码组织。在C++中,extern关键字可用于在源文件之间共享变量。它告诉编译器某个变量的声明在其他源文......
  • 最长子字符串的长度(二)【华为OD机试JAVA&Python&C++&JS题解】
    一.题目-最长子字符串的长度(二)给你一个字符串s,字符串s首尾相连成一个环形,请你在环中找出’l’、‘o’、‘x’字符都恰好出现了偶数次最长子字符串的长度。输入描述:输入是一串小写的字母组成的字符串。输出描述:输出是一个整数补充说明:1<=s.length<=5x10^5......
  • 孙悟空吃蟠桃【华为OD机试JAVA&Python&C++&JS题解】
    一.题目-孙悟空吃蟠桃孙悟空爱吃蟠桃,有一天趁着蟠桃园守卫不在来偷吃。已知蟠桃园有N颗桃树,每颗树上都有桃子,守卫将在H小时后回来。孙悟空可以决定他吃蟠桃的速度K(个/小时),每个小时选一颗桃树,并从树上吃掉K个,如果树上的桃子少于K个,则全部吃掉,并且这一小时剩余的时间里不再......
  • C++学生信息管理 1.0记录
    C++学生信息管理1.0记录 该信息管理没有太多可支持的操作,仅有一些基础设置,后续优化中将添加更多功能。一.头文件引用和命名空间声明#include<iostream>//输入输出操作#include<string>//字符串操作usingnamespacestd;//为方便使用,不需要在cout,string等前方加......