进程与多线程

一、进程(Process)

  1. 概念
    进程是计算机中程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。它可以理解为一个正在执行的程序实例,拥有自己独立的地址空间、代码段、数据段、堆栈等资源。例如,当你打开一个文本编辑器,操作系统就会为这个文本编辑器创建一个进程,这个进程有它自己的内存空间来存储正在编辑的文本内容、程序的代码以及各种运行时的数据。

  2. 进程的特点

    • 独立性:不同进程之间的地址空间相互独立,一个进程不能直接访问另一个进程的内存数据,这保障了进程之间不会相互干扰。
    • 资源拥有性:进程拥有系统分配的各种资源,如 CPU 时间片、内存、文件句柄等。
    • 并发性:多个进程可以在宏观上同时运行,操作系统通过调度算法在多个进程之间切换 CPU 资源,使得每个进程都能得到执行机会。

二、线程(Thread)

  1. 概念
    线程是进程中的一个执行单元,是 CPU 调度和分派的基本单位。一个进程可以包含多个线程,这些线程共享进程的地址空间和资源,如代码段、数据段和打开的文件等。线程可以看作是在进程内部并发执行的路径,它们协同工作来完成进程的任务。例如,在一个网络浏览器进程中,可能有一个线程负责接收用户输入(如输入网址),一个线程负责从服务器下载网页数据,还有一个线程负责渲染页面,这些线程共同完成浏览器的功能。

  2. 线程的特点

    • 轻量级:线程比进程更轻量级,创建和销毁线程的开销比进程小得多。因为线程共享进程的大部分资源,不需要像创建进程那样重新分配大量的系统资源。
    • 共享资源:线程之间可以方便地共享进程内的数据,但这也需要注意对共享资源的同步访问问题,否则可能会导致数据不一致。
    • 并发性:和进程类似,多个线程在一个进程内可以并发执行,提高了程序的执行效率。

三、创建线程(C 语言使用 POSIX 线程库 pthread)

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
#include <unistd.h>
#include <stdio.h>
#include<pthread.h>
#include<string.h>
//定义线程函数:线程函数是线程执行的代码逻辑,它的返回值类型是 void *,参数类型是 void *。例如:
void *rout(void* args)
{int i;for(; ;)                                                                                                                                                                                                   {printf("I am thread-%d",i);sleep(1);// 获取当前线程的线程IDpthread_t t = pthread_self();}
}
int main() {pthread_t tid;int ret;ret=pthread_create(&tid,NULL,&rout,NULL);if(ret<0){}int i;for(; ;){printf("main thread\n");sleep(1);}return 0;}

四、多线程的其他操作

1.线程等待(pthread_join)
使用 pthread_join 函数可以让一个线程等待另一个线程结束。其函数原型为:
int pthread_join(pthread_t thread, void **retval);
其中,thread 是要等待的线程标识符,retval 是用于接收被等待线程的返回值(如果线程函数有返回值的话)的指针。例如:

#include <stdio.h>
#include <pthread.h>void *thread_function(void *arg) {for (int i = 0; i < 10; i++) {printf("This is a thread: %d\n", i);}return NULL;
}int main() {pthread_t thread_id;pthread_create(&thread_id, NULL, thread_function, NULL);void *thread_result;pthread_join(thread_id, &thread_result);for (int i = 0; i < 10; i++) {printf("This is the main thread: %d\n", i);}return 0;
}

在这个例子中,主线程会等待新创建的线程执行完毕后再继续执行自己的循环

2.线程终止(pthread_exit)
线程可以通过调用 pthread_exit 函数来终止自己。其函数原型为:
void pthread_exit(void *retval);
例如:

#include <stdio.h>
#include <pthread.h>void *thread_function(void *arg) {for (int i = 0; i < 5; i++) {printf("This is a thread: %d\n", i);}pthread_exit(NULL);
}int main() {pthread_t thread_id;pthread_create(&thread_id, NULL, thread_function, NULL);void *thread_result;pthread_join(thread_id, &thread_result);printf("Thread has terminated.\n");return 0;
}

在这个线程函数中,线程执行到 pthread_exit 时就会终止,主线程会通过 pthread_join 检测到线程结束。

3.线程同步(互斥锁 pthread_mutex)

同步问题是保证数据安全的情况下,让我们的线程访问资源具有一定的顺序性。

初始化互斥锁:使用 pthread_mutex_init 函数初始化互斥锁,例如:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;(这种静态初始化方式适用于简单情况)或者

pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);

加锁和解锁:在访问共享资源之前使用 pthread_mutex_lock 函数加锁,访问完成后使用 pthread_mutex_unlock 函数解锁。例如:

售票存在问题:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int ticket = 100;
void *route(void *arg)
{char *id = (char*)arg;while ( 1 ) {if ( ticket > 0 ) {usleep(1000);printf("%s sells ticket:%d\n", id, ticket);ticket--;} else {break;}}
}
int main( void )
{pthread_t t1, t2, t3, t4;pthread_create(&t1, NULL, route, "thread 1");pthread_create(&t2, NULL, route, "thread 2");pthread_create(&t3, NULL, route, "thread 3");pthread_create(&t4, NULL, route, "thread 4");pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_join(t4, NULL);
}

解决办法:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
int ticket=100;
pthread_mutex_t mutex;
void *route(void*arg)
{char *id =(char*)arg;while(1){pthread_mutex_lock(&mutex);if(ticket>0){usleep(1000);printf("%s sells ticket:%d\n",id,ticket);ticket--;pthread_mutex_unlock(&mutex);}else{exit(1);pthread_mutex_unlock(&mutex);}}
}
int main()
{pthread_t t1,t2,t3,t4;pthread_mutex_init(&mutex,NULL);pthread_create(&t1,NULL,route,"thread 1");pthread_create(&t2,NULL,route,"thread 2");pthread_create(&t3,NULL,route,"thread 3");pthread_create(&t4,NULL,route,"thread 4");pthread_join(t1,NULL);pthread_join(t2,NULL);pthread_join(t3,NULL);pthread_join(t4,NULL);pthread_mutex_destroy(&mutex);
}

4.线程间的条件变量

条件变量用于线程间的同步,通常与互斥锁一起使用。一个线程可以等待某个条件变量满足,而另一个线程可以在条件满足时唤醒等待该条件变量的线程。

初始化条件变量:使用 pthread_cond_init 函数初始化条件变量,例如:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;(静态初始化)或者

pthread_cond_t cond;
pthread_cond_init(&cond, NULL);

等待条件变量:使用 pthread_cond_wait 函数等待条件变量,它会自动释放互斥锁并阻塞线程,直到条件变量被唤醒。例如

pthread_mutex_t mutex;
pthread_cond_t cond;
int data_ready = 0;void *thread_function(void *arg) {pthread_mutex_lock(&mutex);while (!data_ready) {pthread_cond_wait(&cond, &mutex);}// 这里是条件满足后执行的代码pthread_mutex_unlock(&mutex);return NULL;
}int main() {// 初始化互斥锁和条件变量pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);pthread_t thread;pthread_create(&thread, NULL, thread_function, NULL);// 模拟数据准备好的情况pthread_mutex_lock(&mutex);data_ready = 1;pthread_cond_signal(&cond); // 唤醒等待条件变量的线程pthread_mutex_unlock(&mutex);pthread_join(thread, NULL);return 0;
}

在这个例子中,一个线程等待 data_ready 条件满足,主线程在准备好数据后通过 pthread_cond_signal 唤醒等待的线程。

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

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

相关文章

ElementUI之给el-table实现搜索功能

1&#xff0c;有一个表格 <el-table:data"tableData"borderstyle"width: 100%"><el-table-columnprop"date"label"日期"width"180"></el-table-column><el-table-columnprop"name"label&quo…

Chrome 浏览器 131 版本开发者工具(DevTools)更新内容

Chrome 浏览器 131 版本开发者工具&#xff08;DevTools&#xff09;更新内容 一、使用 Gemini 调试 CSS Chrome DevTools 现在推出了一个新的实验性 AI 辅助面板&#xff0c;可以与 Gemini 聊天并获得帮助来调试 CSS。 在 Elements 面板中&#xff0c;右键点击一个元素并选…

Ubuntu20.04 Rk3588 交叉编译ffmpeg7.0

firefly 公司出的rk3588的设备&#xff0c;其中已经安装了gcc 交叉编译工具&#xff0c;系统版本是Ubuntu20.04。 使用Ubuntu20.04 交叉编译ffmpeg_ubuntu下配置ffmpeg交叉编译器为arm-linux-gnueabihf-gcc-CSDN博客文章浏览阅读541次。ubuntu20.04 交叉编译ffmpeg_ubuntu下配…

蓝桥杯第22场小白入门赛2~5题

这场比赛开打第二题就理解错意思了&#xff0c;还以为只能用3个消除和5个消除其中一种呢&#xff0c;结果就是死活a不过去&#xff0c;第三题根本读不懂题意&#xff0c;这蓝桥杯的题面我只能说出的是一言难尽啊。。第四题写出来一点但是后来知道是错了&#xff0c;不会正解&am…

sagemaker中使用pytorch框架的DLC训练和部署cifar图像分类任务

参考资料 https://github.com/aws/amazon-sagemaker-examples/blob/main/sagemaker-python-sdk/pytorch_cnn_cifar10/pytorch_local_mode_cifar10.ipynbhttps://sagemaker.readthedocs.io/en/stable/frameworks/pytorch/using_pytorch.html 获取训练数据 # s3://zhaojiew-sa…

golang笔记8-函数

1. 基本函数 package mainimport "fmt"/*什么是函数&#xff1a;完成某一功能的程序指令的集合语法&#xff1a;func 函数名称(形参列表)(返回值类型列表){执行语句。。。返回值列表}注意事项&#xff1a;函数名&#xff1a;函数名首字母大写&#xff1a;可以被本包…

vite+vue3+ts编译vue组件后,编译产物中d.ts文件为空

一、前言 使用vue3vitets实现一个UI组件库&#xff0c;为了生成类型文件便于其他项目引用该组件库。根据推荐使用了vite-plugin-dts插件进行ts文件的生成 二、版本 组件版本vue ^3.5.12 vite ^5.4.10 vite-plugin-dts ^4.3.0 typescript ~5.6.2 三、问题描述 使用vitevi…

向量数据库FAISS之二:基础进阶版

基础 1.评价类型和距离 1.METRIC_L2 Faiss 使用了欧几里得 (L2) 距离的平方&#xff0c;避免了平方根。 这仍然与欧几里德距离一样单调&#xff0c;但如果需要精确距离&#xff0c;则需要结果的额外平方根。 2.METRIC_INNER_PRODUCT 这通常用于推荐系统中的最大内积搜索。…

家庭网络常识:猫与路由器

这张图大家应该不陌生——以前家庭网络的连接方式。 图1 家庭网络连接示意图 来说说猫/光猫&#xff1a; 先看看两者的图片。 图2 猫 图3 光猫 这个东西因为英文叫“modem”&#xff0c;类似中文的“猫”&#xff0c;所以简称“猫”。 猫和光猫的区别就是&#xff0c;一…

华三预赛学习笔记(每日编辑,复习完为止)

知识点分布 路由交换技术基础 计算机网络基本概念 计算机网络基本概念&#xff1a; 很多电脑和设备通过电线或无线信号连在一起&#xff0c;可以互相“说话”和“分享东西” 网络的主要形式和发展历程&#xff1a; 诞生阶段-最早的计算机网络是以单个计算机为中心的联机系统-终…

技术速递|Microsoft.Extensions.VectorData 预览版简介

作者&#xff1a;Luis Quintanilla - 项目经理 排版&#xff1a;Alan Wang 我们很高兴推出 Microsoft.Extensions.VectorData.Abstractions 库&#xff0c;该库现已提供预览版。 正如 Microsoft.Extensions.AI 库为使用 AI 服务提供了一个统一层一样&#xff0c;此包为 .NET 生…

第5章-总体设计 5.3 硬件架构设计

5.3 硬件架构设计 1.哪些类型的产品需要架构设计&#xff1f;2.硬件架构师到底做什么&#xff1f;&#xff08;1&#xff09;理解需求和业务模型的情况。&#xff08;2&#xff09;背板设计&#xff0c;既需要考虑业务数据交换能力&#xff0c;也需要考虑子模块的管理监控能力。…

图像/文字差异类型验证码识别 无需训练

某像差异在个别全家桶验证方便有使用&#xff0c;对于这种验证码类型如下&#xff1a; 首先还是目标检测&#xff0c;直接用 dddd 自带的detection 就足够了。 特征提取 其次经过观察&#xff0c;差异答案与其他三个无非就是颜色&#xff0c;字体&#xff0c;方向&#xff0c…

新华三H3CNE网络工程师认证—生成树协议

新华三H3CNE网络工程师认证本节讲解生成树协议&#xff0c;关于生成树协议&#xff0c;提到生成树协议&#xff0c;这个时候不得不提到另外一个概念叫二层环路。二层环路导致的原因是交换机的转发机制导致的&#xff0c;本博客将分析这个机制导致这个问题的原因。 文章目录 一…

使用ai工具探究论文的工作流(阅读一个EEG的cnn-lstm文献(2021))

文章目录 李沐老师的方法论第一遍&#xff1a;做海选第二遍&#xff1a;对相关论文进行精选第三遍&#xff1a;重点研读 AI是怎么分析一个文章的标题&#xff08;Title&#xff09;和关键词摘要&#xff08;Abstract&#xff09;分析引言&#xff08;Introduction&#xff09;梳…

Scala的Array习题

答案&#xff1a;CBBBB import scala.collection.mutable.ArrayBuffer //1 case class DreamItem(content:String,var isDone:Boolean,deadline:String,var order:Int) object p5 {def main(args: Array[String]): Unit {//2val dreamListArrayBuffer[DreamItem]()//梦想清单/…

深度学习的实践层面

深度学习的实践层面 设计机器学习应用 在训练神经网络时&#xff0c;超参数选择是一个高度迭代的过程。我们通常从一个初步的模型框架开始&#xff0c;进行编码、运行和测试&#xff0c;通过不断调整优化模型。 数据集一般划分为三部分&#xff1a;训练集、验证集和测试集。常…

TPU-MLIR 总览

TPU-MLIR 总览 &#x1f4a1;深度学习编译器可以实现一次性代码开发和重用各种计算能力处理器的目标 ## 项目简介&#xff1a; TPU-MLIR 是 AI 芯片的 TPU 编译器工程。该工程提供了一套完整的工具链, 其可以将不同框架下预训练的神经网络, 转化为可以在算能 TPU 上高效运算的…

Vue3 + Vite 项目引入 Typescript

文章目录 一、TypeScript简介二、TypeScript 开发环境搭建三、编译方式1. 自动编译单个文件2. 自动编译整个项目 四、配置文件1. compilerOptions基本选项严格模式相关选项&#xff08;启用 strict 后自动包含这些&#xff09;模块与导入相关选项 2. include 和 excludeinclude…

苹果MacOS 调用自编译opencv的Dylib显示一个图片程序的步骤

前言 为了测试自编译的opencv库是否能在苹果MacOS系统下使用&#xff0c;需要写一个简单的测试程序。这个测试程序写起来不难&#xff0c;麻烦的是一些配置。网上的办法很多&#xff0c;里面因为版本的问题有一些坑。特此写了一个建立步骤&#xff0c;供大家参考。 1、新建一个…