Linux18 ---进程和线程、线程实现方法、线程的使用接口、多线程代码实现、线程并发运行

news2025/7/29 22:02:51

一、进程和线程:

1、进程和线程的相关概念:

进程:是一个正在运行的程序,是个动态的概念。一个进程可以实现多个线程。

线程:是进程内部的一条执行路径或称为执行序列,不同平台下线程的实现机制不相同,但都被称为线程。
在这里插入图片描述

在这里插入图片描述

2、进程和线程的区别:

进程是资源分配的最小单位,线程是CPU 调度的最小单位。
进程有自己的独立地址空间,线程共享进程中的地址空间。
进程的创建消耗资源大,线程的创建相对较小。
进程的切换开销大,线程的切换开销相对较小。

二、线程实现方法

在操作系统中,线程的实现有以下三种方式:

用户级线程:开销小,但无法使用多个处理器;
内核级线程:相对来讲开销大,可以利用多个处理器;
组合级模型

在这里插入图片描述

Linux中线程的实现:

Linux实现线程的机制非常独特。从内核的角度来说,它并没有线程这个概念。Linux把所有的线程都当做进程来实现。内核并没有准备特别的调度算法或是定义特别的数据结构来表征线程。相反,线程仅仅被视为一个与其他进程共享某些资源的进程。每个线程都拥有唯一隶属于自己的 task_struct,所以在内核中,它看起来就像是一个普通的进程(只是线程和其他一些进程共享某些资源,如地址空间)。

三、线程的使用

1、头文件

#include <pthread.h>

编译时需要带上 -lpthread
在这里插入图片描述

2、创建线程 --pthread_create

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

pthread_create() :用于创建线程
thread :接收创建的线程的
IDattr :指定线程的属性
start_routine :指定线程函数
arg :给线程函数传递的参数,成功返回0,失败返回错误码

3、退出线程–pthread_exit

int pthread_exit(void *retval);
pthread_exit() :退出线程。
retval :指定退出信息。

4、等待线程结束/合并线程–pthread_join()

int pthread_join(pthread_t thread, void**retval);
pthread_join() :等待thread指定的线程退出,线程未退出时,该方法阻塞;
retval :接收thread 线程退出时,指定的退出信息

四、多线程代码实现

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>

#include <pthread.h>

//线程函数fun
void* pthread_fun(void* arg)
{
    int i = 0;
    
    for(;i < 5;++i)
    {
    	sleep(1);
        printf("fun thread running\n");
    }
    
    //退出线程
    pthread_exit("fun over");
}

int main()
{
    //创建线程id
    pthread_t id;//该地址由pthread_create创建,其创建后会自动写入,不需要自己定义
    //创建线程
    //pthread_create(&id,NULL,pthread_fun,NULL);
    int res = pthread_create(&id,NULL,pthread_fun,NULL);//创建了fun线程函数
    assert(res == 0);

    int i = 0;
    for(; i < 5; i++)
    {
    	sleep(1);
        printf("main thread running\n");
    }

    //等待thread指定的线程退出,线程未退出时,该方法阻塞;
    char *s = NULL;
    pthread_join(id,(void **)&s);//将二级指针强转成void类型的

    printf("s = %s\n",s);

    exit(0);
}

运行结果:
在这里插入图片描述

不加sleep,难以观察到并发运行的发生:
在这里插入图片描述

五、线程并发运行(不加同步)

1、并发和并行

并发和并行(并行需要多个处理器,但多个处理器不一定是并行运行,因为要共享资源):
在这里插入图片描述

2、一次创建5个线程,让每个线程打印自己是第几个被创建的。

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

void* thread_fun(void* arg)
{
    int index = *((int *)arg);

    int i = 0;
    printf("index = %d\n",index);
        
    sleep(1);
}

int main()
{
    //创建五个线程
    pthread_t id[5];
    int i = 0;
    for(; i < 5 ; i++)
    {
        pthread_create(&id[i],NULL,thread_fun,(void*)&i);
    }

    for( i = 0; i < 5 ; i++)
    {
        pthread_join(id[i],NULL);
    }

    exit(0);
}

运行结果:
发现输出的值每次运行都太不一样。
这里输出的index 是其运行输出函数时,那一刻所获取的 i 的值。而i的值该程序有三个函数再使用 i。而这个循环的执行速度非常快,所以获取i的值就会出错。
后面的0,较大概率是最后一个for循环的0。因为这里有pthread_join() (等待thread指定的线程退出,线程未退出时,该方法阻塞)。

在这里插入图片描述

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

void* thread_fun(void* arg)
{
    int index = *((int *)arg);

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

int main()
{
    //创建五个线程
    pthread_t id[5];
    int i = 0;
    for(; i < 5 ; i++)
    {
        pthread_create(&id[i],NULL,thread_fun,(void*)&i);
    }

    for( i = 0; i < 5 ; i++)
    {
        pthread_join(id[i],NULL);
    }

    exit(0);
}

在这里插入图片描述
在这里插入图片描述

3、创建5个线程,同时对一个全局变量进行++,加到5000

测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

int g = 0;

void* thread_fun(void* arg)
{
    int i = 0;
    for(; i < 1000; i++)
    {
        printf("g = %d\n",++g);
    }
}

int main()
{
    pthread_t id[5];

    int i = 0;
    for(; i < 5; i++)
    {
        pthread_create(&id[i],NULL,thread_fun,NULL);
    }

    for( i = 0; i < 5; i++)
    {
        pthread_join(id[i],NULL);
    }
   
    exit(0);
}

运行结果:

多处理器测试:

发现最终所得值小于等于5000;

在这里插入图片描述
在这里插入图片描述

单处理器测试:

在这里插入图片描述

结果都为5000

在这里插入图片描述在这里插入图片描述

对于main.c ,计算机不能直接执行,编译好生成的main.exe/main ,程序由一条条指令构成,内部指令的排序格式:ELF(linux)、PE(Windows)。所以对于一个a+b运行时,最终最终转换成指令会是多条指令。而我们要将内存中的一个值进行++操作时,需要将其读到cpu里,由cpu内部的加法器进行++操作后,再写回内存。所以对于上面的代码,对g进行++的时候,对于多个并行线程对其++,就有可能在一个线程进行++的过程中,还没完成时,另一个线程错误获取了g,导致两个对其同时进行++,只+1;而循环次数却+2。所以回小于5000。

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

基于Android车载系统模块资料

在从事车载Android应用开发前&#xff0c;必须要对汽车座舱的基本结构有一个大体的认知&#xff0c;只有意识到汽车座舱是一种与手机完全不同的架构&#xff0c;才能更好的助力我们日后学习车载Android应用的开发。下面就来介绍一个比较主流的车载操作系统架构。 注意&#xff…

Unity实现一个可扩展的UGUI无限滑动列表控件

采用 缓存池存储布局坐标 实现的一个可横向或纵向滑动的无限滑动列表 Demo展示&#xff1a; 功能支持&#xff1a; 可以满足大部分如背包&#xff0c;商店商城&#xff0c;工具栏&#xff0c;任务栏窗口等列表功能 支持整个列表刷新或单个对象刷新支持横向多行滑动&#xff…

【Python】快速入门

目录 基础储备 Python输出&#xff1a; Python换行&#xff1a; Python命名规则&#xff1a; Python变量: Python运算&#xff1a; Python注释&#xff1a; 小点&#xff1a; Python的两种模式&#xff1a; Python的用户问答互动程序&#xff1a; Python条件语句 P…

Kubernetes-in-action (一)

Kubernetes-in-action (一) 链接为书内容中对应代码的地址&#xff1a;https://github.com/luksa/kubernetes-in-action 前置之 docker 基础 安装docker使用docker安装镜像、进入镜像&#xff0c;查看进行信息docker build -t kubia . # 使用当前目录的Dockerfile构建镜像&…

m基于Matlab的fir和iir数字滤波器的设计与仿真

目录 1.算法概述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法概述 MATLAB系统供了许多工具箱&#xff08;Toolbox&#xff09;&#xff0c;借助于信号处理工具箱&#xff08;signal processing&#xff09;中的freqz_m&#xff0c;remez等函数&#xff0…

软件测试 | 测试工程师都能看懂的redis,进阶测试开发工程师......

目录&#xff1a;导读前言一、Redis是什么&#xff1f;为啥性能好&#xff1f;二、数据类型&#xff1f;常见的命令&#xff1f;1、String 字符串类型2、Hash 数据类型3、List 链表数据4、Set 无序集合类型5、Zset 有序集合类型三、有几种持久化方式&#xff1f;优缺点?四、数…

Flink-输出算子(Sink)使用

5.5 输出算子 5.5.1 概述 print也是一种输出类PrintSinkFunction 创建了一个PrintSinkFunction操作&#xff0c;然后调用addSink方法的作为传入参数 PrintSinkFunction这个类继承自RichSinkFunction富函数类 RichSourceFunction类 继承了AbstractRichFunction富函数类 …

springboot2整合开发流程示例

1.整体开发逻辑 初始配置示例 开发文件示例 2.开发过程问题 ①默认配置路径 thymeleaf默认解析静态资源路径为 /templates/** ②mybatisplus核心工作原理 mapper继承的BaseMapper中声明了CRUD操作service接口继承的IService接口中抽象方法简单封装了CRUD操作 传入了类&a…

Win10系统如何安装配置maven

【原文链接】Win10系统如何安装配置maven &#xff08;1&#xff09;若未装jdk&#xff0c;可先参考 Win10系统下载安装配置JDK1.8 安装jdk8 &#xff08;2&#xff09;从 maven下载地址 &#xff0c;下载maven&#xff0c;如下&#xff0c;可以下载最新版本&#xff0c;也可…

【JVM】JVM详解

目录一.JVM概述1.jvm简介2.jvm作用3.jvm的内存模型二.类加载器1.类加载器的作用2.加载器的类型3.双亲委派机制的运行过程(面试题)三.JVM内存模块1.方法区2.堆3.栈(虚拟机栈)4.栈(本地方法栈)5.OutOfMemoryError内存溢出和StackOverFlowError栈溢出及解决方法(面试题)(1).OutOfM…

利用ogg微服务版将oracle同步到kafka

ogg微服务版可以再界面上配置抽取、复制进程&#xff0c;不必进入到shell中进行配置&#xff0c;并且图形化界面可以看到更多信息。 系统架构 源端安装ogg for oracle 19C , 目标端安装ogg for bigdata 21C kafka 2.2 数据库&#xff1a;19C 所有软件安装在同台服务器上&#…

操作系统4小时速成:文件管理,文件结构,属性,基本操作,逻辑有无结构,目录结构,文件系统

操作系统4小时速成&#xff1a;文件管理&#xff0c;文件结构&#xff0c;属性&#xff0c;基本操作&#xff0c;逻辑有无结构&#xff0c;目录结构&#xff0c;文件系统 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能…

2397. 被列覆盖的最多行数-深度优先枚举+二进制检索

2397. 被列覆盖的最多行数-深度优先枚举二进制检索 给你一个下标从 0 开始的 m x n 二进制矩阵 mat 和一个整数 cols &#xff0c;表示你需要选出的列数。 如果一行中&#xff0c;所有的 1 都被你选中的列所覆盖&#xff0c;那么我们称这一行 被覆盖 了。 请你返回在选择 co…

Spring Security内部工作原理

定义 Spring 安全性是 Spring提供的一个框架&#xff0c;有助于自定义访问和身份验证过程。它在保护应用程序方面起着非常关键的作用。 Spring 安全性&#xff0c;主要侧重于身份验证和授权&#xff0c;为 Java 应用程序提供所有好处。它非常有用&#xff0c;并提供了一种在实…

抑制细胞代谢紊乱的抑制剂

作者团队发现&#xff0c;缺乏 CD4 T 细胞能保护小鼠免受应激诱导的焦虑样行为&#xff0c;物理应激诱导的白三烯 B4 (LTB4) 触发 CD4 T 细胞中的严重线粒体裂变&#xff0c;进而导致各种行为异常&#xff0c;包括焦虑&#xff0c;抑郁和社交障碍。代谢组和单细胞转录组学显示…

Android App实战项目之实现手写签名APP功能(附源码,简单易懂 可直接实用)

运行有问题或需要源码请点赞关注收藏后评论区留言~~~ 一、跟踪滑动轨迹实现手写签名 手写签名的原理是把手机屏幕当作画板&#xff0c;把用户手指当作画笔&#xff0c;手指在屏幕上划来划去&#xff0c;屏幕就会显示手指的移动轨迹&#xff0c;就像画笔在画板上写字一样&#…

安装free IPA与CDH6.3.2结合

主机名之类的应该在cdh安装的时候就配好了 不再赘述 安装freeipa yum -y install nscd 修改 enable-cache netgroup no enable-cache group no enable-cache passwd no 云主机默认不开启IPv6&#xff0c;根据提…

小 A 的卡牌游戏(Gym - 103186B)

题 小A最近沉迷于-款名为Hearthverse的卡牌游戏。在这款游戏中&#xff0c;卡被分为了三个种类(随从、法术和魔法阵)&#xff0c;在组卡时&#xff0c;这款游戏严格规定了卡组中每种卡牌的数量&#xff0c;具体来说&#xff0c;-副n张卡的卡组需要包含恰好a张随从卡&#xff0…

Tdengine技术实践

1. 什么是时序数据库&#xff1f; 时序数据库全称为时间序列数据库。 即时间序列数据&#xff0c;按时间维度顺序记录且索引的数据。 时间序列数据主要由 电力行业、化工行业、气象行业、地理信息 等各类型实时监测、检查与分析设备所采集、产生的数据&#xff0c;这些工业数…

配置Maven环境

Maven官网 Maven所有发行版本 一、windows配置maven环境 想要使用maven就必须要有JDK JDK安装 百度网盘下载&#xff08;二进制文件&#xff0c;一直点下去&#xff09; 链接&#xff1a;https://pan.baidu.com/s/1y1AutzJeQGdNHa2ml_bk8w 提取码&#xff1a;scyc验证JDK是…