线程和进程的区别及基础线程创建
1 线程和进程的区别
-
资源分配和调度:
- 进程(火车)是操作系统进行资源分配和调度的最小单位。它有自己的独立资源空间,包括内存、文件句柄等。
- 线程(车厢)是CPU调度的最小单位。一个进程可以包含多个线程,它们共享相同的资源空间,如内存,但有各自的执行路径。
-
数据共享:
- 进程间的数据共享相对困难,需要使用进程间通信(IPC)的机制。
- 同一进程内的不同线程可以直接共享数据,因为它们共享相同的内存空间。
-
稳定性和影响范围:
- 进程间是相互独立的,一个进程的崩溃通常不会影响其他进程。
- 同一进程下的线程是共享相同的进程资源,一个线程的崩溃可能导致整个进程崩溃。
-
资源消耗和扩展性:
- 进程比线程消耗更多的计算机资源,因为它们有独立的资源空间。
- 进程可以在多台机器上运行,而线程适合在多核处理器上运行。
-
内存地址管理:
- 进程的内存地址可以上锁,实现互斥访问,确保线程安全。
- 进程的内存地址可以限定使用量,通过信号量等机制控制资源的访问。
这个比喻涵盖了进程和线程的许多关键概念,希望能够更好地帮助理解它们之间的区别和关系。
2 基础线程创建
2.1 代码示例
以下最简单的事例来理解线程:
//test.cpp
#include <iostream>
#include <pthread.h> //必须的头文件using namespace std;#define NUM_THREADS 5// 线程的运行函数
void* say_hello(void* args)
{cout << "Hello Runoob!" << endl;return 0;
}int main()
{// 定义线程的 id 变量,多个变量使用数组pthread_t tids[NUM_THREADS];for(int i = 0; i < NUM_THREADS; ++i){//参数依次是:创建的线程id,线程参数,调用的函数,传入的函数参数int ret = pthread_create(&tids[i], NULL, say_hello, NULL);if (ret != 0){cout << "pthread_create error: error_code=" << ret << endl;}}//等各个线程退出后,进程才结束,否则进程强制结束了,线程可能还没反应过来;//**当linux中,主线程以pthread_exit(NULL)作为返回值,则主线程会等待子线程。**pthread_exit(NULL);}
2.2 线程代码编译
2.2.1 命令行编译
使用 -lpthread 库编译下面的程序:
$ g++ test.cpp -lpthread -o test.o
2.2.2 Makefile编译
但是如果用Makefile一堆文件编译的情况下如何设置
# Makefile中变量定义如:标签=内容,后面的变量引用需要$(标签)
GPU=0
CUDNN=0
OPENCV=0
OPENMP=0 # OpenMP是一套支持跨平台共享内存方式的多线程并发的编程API
DEBUG=0ARCH= -gencode arch=compute_30,code=sm_30 \-gencode arch=compute_35,code=sm_35 \-gencode arch=compute_50,code=[sm_50,compute_50] \-gencode arch=compute_52,code=[sm_52,compute_52]
# -gencode arch=compute_20,code=[sm_20,sm_21] \ This one is deprecated?# This is what I use, uncomment if you know your arch and want to specify
# ARCH= -gencode arch=compute_52,code=compute_52VPATH=./src/:./examples
SLIB=libdarknet.so #待生成的动态链接库
ALIB=libdarknet.a #待生成的静态链接库
EXEC=darknet #待生成的执行文件名称
OBJDIR=./obj/ #生成目标文件的目录,即当期目录下obj子目录CC=gcc
CPP=g++
NVCC=nvcc #nvidia编译器
AR=ar #ar,Linux系统的一个备份压缩命令,用于创建、修改备存文件(archive)。这里的ar命令是将目标文件打包为静态链接库。
ARFLAGS=rcs #ar命令的参数 -rcs。-r:将文件插入备存文件中 c:建立备存文件 s:若备存文件中包含了对象模式,可利用此参数建立备存文件的符号表
OPTS=-Ofast
#编译选项中指定 -pthread 会附加一个宏定义 -D_REENTRANT,该宏会导致 libc 头文件选择那些thread-safe的实现;
#链接选项中指定 -pthread 则同 -lpthread 一样,只表示链接 POSIX thread 库。由于 libc 用于适应 thread-safe 的宏定义可能变化,
#因此在编译和链接时都使用 -pthread 选项而不是传统的 -lpthread 能够保持向后兼容,并提高命令行的一致性。
LDFLAGS= -lm -pthread
COMMON= -Iinclude/ -Isrc/
#-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
#unknow-pragmas:使用未知的#pragma指令
CFLAGS=-Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC ifeq ($(OPENMP), 1) #条件判断
CFLAGS+= -fopenmp
endififeq ($(DEBUG), 1)
OPTS=-O0 -g #-g选项可以产生带有调试信息的目标代码
endifCFLAGS+=$(OPTS)ifeq ($(OPENCV), 1)
COMMON+= -DOPENCV #相当于C语言中的#define OPENCV
CFLAGS+= -DOPENCV
LDFLAGS+= `pkg-config --libs opencv` -lstdc++ #pkg-config能够把头文件和库文件的位置指出来,给编译器使用
COMMON+= `pkg-config --cflags opencv`
endififeq ($(GPU), 1)
COMMON+= -DGPU -I/usr/local/cuda/include/
CFLAGS+= -DGPU
LDFLAGS+= -L/usr/local/cuda/lib64 -lcuda -lcudart -lcublas -lcurand
endififeq ($(CUDNN), 1)
COMMON+= -DCUDNN
CFLAGS+= -DCUDNN
LDFLAGS+= -lcudnn
endif#OBJ表示需要生成的目标文件
OBJ=gemm.o utils.o cuda.o deconvolutional_layer.o convolutional_layer.o list.o image.o activations.o im2col.o col2im.o blas.o crop_layer.o dropout_layer.o maxpool_layer.o softmax_layer.o data.o matrix.o network.o connected_layer.o cost_layer.o parser.o option_list.o detection_layer.o route_layer.o upsample_layer.o box.o normalization_layer.o avgpool_layer.o layer.o local_layer.o shortcut_layer.o logistic_layer.o activation_layer.o rnn_layer.o gru_layer.o crnn_layer.o demo.o batchnorm_layer.o region_layer.o reorg_layer.o tree.o lstm_layer.o l2norm_layer.o yolo_layer.o iseg_layer.o image_opencv.o
EXECOBJA=captcha.o lsd.o super.o art.o tag.o cifar.o go.o rnn.o segmenter.o regressor.o classifier.o coco.o yolo.o detector.o nightmare.o instance-segmenter.o darknet.o
ifeq ($(GPU), 1)
LDFLAGS+= -lstdc++
OBJ+=convolutional_kernels.o deconvolutional_kernels.o activation_kernels.o im2col_kernels.o col2im_kernels.o blas_kernels.o crop_layer_kernels.o dropout_layer_kernels.o maxpool_layer_kernels.o avgpool_layer_kernels.o
endifEXECOBJ = $(addprefix $(OBJDIR), $(EXECOBJA)) #addprefix统一添加前缀
OBJS = $(addprefix $(OBJDIR), $(OBJ))
DEPS = $(wildcard src/*.h) Makefile include/darknet.h #wildcard展开src文件下所有后缀为.h的头文件;all: obj backup results $(SLIB) $(ALIB) $(EXEC) #主要任务all和其所有依赖
#all: obj results $(SLIB) $(ALIB) $(EXEC)$(EXEC): $(EXECOBJ) $(ALIB)$(CC) $(COMMON) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(ALIB) #$@自动变量,表示目标名称,这里指$(EXEC),实际为darknet;$^指代所有前置条件,之间以空格分隔$(ALIB): $(OBJS)$(AR) $(ARFLAGS) $@ $^ $(SLIB): $(OBJS)$(CC) $(CFLAGS) -shared $^ -o $@ $(LDFLAGS) #-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件$(OBJDIR)%.o: %.cpp $(DEPS)$(CPP) $(COMMON) $(CFLAGS) -c $< -o $@ #$<指代第一个前置条件,这里指%.cpp; -c编译、汇编到目标代码,不进行链接$(OBJDIR)%.o: %.c $(DEPS)$(CC) $(COMMON) $(CFLAGS) -c $< -o $@$(OBJDIR)%.o: %.cu $(DEPS)$(NVCC) $(ARCH) $(COMMON) --compiler-options "$(CFLAGS)" -c $< -o $@obj:mkdir -p obj #-p 确保目录名称存在,不存在的就建一个
backup:mkdir -p backup
results:mkdir -p results.PHONY: cleanclean:rm -rf $(OBJS) $(SLIB) $(ALIB) $(EXEC) $(EXECOBJ) $(OBJDIR)/*
3 线程属性
1、pthread_attr_init
功能: 对线程属性变量的初始化。2、pthread_attr_setscope
功能: 设置线程 __scope 属性。scope属性表示线程间竞争CPU的范围,也就是说线程优先级的有效范围。POSIX的标准中定义了两个值:PTHREAD_SCOPE_SYSTEM和PTHREAD_SCOPE_PROCESS,前者表示与系统中所有线程一起竞争CPU时间,后者表示仅与同进程中的线程竞争CPU。默认为PTHREAD_SCOPE_PROCESS。目前LinuxThreads仅实现了PTHREAD_SCOPE_SYSTEM一值。3、pthread_attr_setdetachstate
功能: 设置线程detachstate属性。该表示新线程是否与进程中其他线程脱离同步,如果设置为PTHREAD_CREATE_DETACHED则新线程不能用pthread_join()来同步,且在退出时自行释放所占用的资源。缺省为PTHREAD_CREATE_JOINABLE状态。这个属性也可以在线程创建并运行以后用pthread_detach()来设置,而一旦设置为PTHREAD_CREATE_DETACH状态(不论是创建时设置还是运行时设置)则不能再恢复到PTHREAD_CREATE_JOINABLE状态。4、pthread_attr_setschedparam
功能: 设置线程schedparam属性,即调用的优先级。5、pthread_attr_getschedparam
功能: 得到线程优先级。
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
static void pthread_func_1 (void);
static void pthread_func_2 (void); int main (int argc, char** argv)
{ pthread_t pt_1 = 0; pthread_t pt_2 = 0; pthread_attr_t atrr = {0}; int ret = 0; //初始化属性线程属性pthread_attr_init (&attr); pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); ret = pthread_create (&pt_1, &attr, pthread_func_1, NULL); if (ret != 0) { perror ("pthread_1_create"); }
**//线程一的线程函数一结束就自动释放资源(因为设置了分离属性)**ret = pthread_create (&pt_2, NULL, pthread_func_2, NULL); if (ret != 0) { perror ("pthread_2_create"); } **//线程二就得等到pthread_join来释放系统资源(因为没有设置分离属性,需要依赖主线程释放资源)**pthread_join (pt_2, NULL); return 0;
} static void pthread_func_1 (void)
{ int i = 0; for (; i < 6; i++) { printf ("This is pthread_1.\n"); if (i == 2) { pthread_exit (0); } } return;
} static void pthread_func_2 (void)
{ int i = 0; for (; i < 3; i ++) { printf ("This is pthread_2.\n"); } return;
}
4 注意内存泄漏问题
在使用pthread_create
函数创建线程时,默认情况下线程是非分离属性的,其分离属性由pthread_create
函数的第二个参数决定。在非分离的情况下,当一个线程结束时,它所占用的系统资源并没有完全释放,也没有真正终止。
- 只有在调用
pthread_join
函数并在其返回时,该线程才会释放自己的资源。 - 或者在设置为分离属性的情况下,一个线程结束会立即释放它所占用的资源。
为了确保在创建线程后避免内存泄漏,必须规范地使用pthread_create
,具体做法是设置线程为分离属性。以下是一个示例代码:
void run() {return;
}int main(){pthread_t thread; // 创建线程idpthread_attr_t attr; // 设置线程属性pthread_attr_init(&attr); // 初始化线程属性pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 设置分离属性// 也可以使用 pthread_attr_setdetachstate(&attr, 1); 来设置分离属性pthread_create(&thread, &attr, run, 0); // 第二个参数决定了分离属性// ......return 0;
}
通过设置线程为分离属性,可以确保在线程结束时即刻释放其占用的资源,有效地防止内存泄漏问题。
5 总结
本文深入探讨了线程和进程的概念,以及它们之间的关键区别。通过一个简单而生动的比喻,将进程比喻为火车,线程比喻为火车的车厢,为读者提供了直观的理解。总体而言,深入理解线程和进程的概念,并掌握基础线程创建和属性设置,对于并发编程和多线程应用的开发至关重要。通过本文的阐述,读者将更好地理解这些概念,并能够在实际应用中更有效地利用线程和进程的优势。
参考
-
线程属性pthread_attr_t简介_猴子居士的博客-CSDN博客_pthread_attr_t详解
-
pthread详解_networkhunter的博客-CSDN博客
-
[C++]多线程: 教你写第一个线程_cn_wk的专栏-CSDN博客_c++怎么写多线程
-
C++ 多线程 | 菜鸟教程 (runoob.com)
-
编译条件“-lpthread”应该加在makefile的哪里阿?-CSDN社区
-
Darknet yolov3 Makefile文件解析_To Be Continue-CSDN博客
-
多线程之pthread_create()函数_wushuomin的博客-CSDN博客_pthread_create
相关文章:
线程和进程的区别及基础线程创建
1 线程和进程的区别 资源分配和调度: 进程(火车)是操作系统进行资源分配和调度的最小单位。它有自己的独立资源空间,包括内存、文件句柄等。线程(车厢)是CPU调度的最小单位。一个进程可以包含多个线程&…...
如何使用postman进行接口调试
使用Postman进行接口调试 有些时候我们写代码的时候,会发现接口有报错,提示参数错误,我们为了更好的排查错误原因,可以在Postman上进行接口调试。将url,请求方式,参数,cookie都填写到Postman中…...
Leetcode 198 打家劫舍
题意理解: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代…...

相机图像质量研究(9)常见问题总结:光学结构对成像的影响--工厂镜头组装
系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结:光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结:光学结构对成…...
Linux内核与驱动面试经典“小”问题集锦(5)
接前一篇文章:Linux内核与驱动面试经典“小”问题集锦(4) 问题6 问:mutex_lock和mutex_lock_interruptible的区别是什么? 备注:此问题也是笔者近期参加蔚来面试时遇到的一个问题。 答: 尽管…...

基于51 单片机的交通灯系统 源码+仿真+ppt
主要内容: 1)南北方向的绿灯、东西方向的红灯同时亮40秒。 2)南北方向的绿灯灭、黄灯亮5秒,同时东西方向的红灯继续亮。 3)南北方向的黄灯灭、左转绿灯亮,持续20秒,同时东西方向的红灯继续…...

【蓝桥杯冲冲冲】[NOIP2017 提高组] 宝藏
蓝桥杯备赛 | 洛谷做题打卡day29 文章目录 蓝桥杯备赛 | 洛谷做题打卡day29[NOIP2017 提高组] 宝藏题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1样例 #2样例输入 #2样例输出 #2提示题解代码我的一些话[NOIP2017 提高组] 宝藏 题目背景 NOIP2017 D2T2 题目描…...

C#中实现串口通讯和网口通讯(使用SerialPort和Socket类)
仅作自己学习使用 1 准备部份 串口通讯需要两个调试软件commix和Virtual Serial Port Driver,分别用于监视串口和创造虚拟串口。网口通讯需要一个网口调试助手,网络上有很多资源,我在这里采用的是微软商店中的TCP/UDP网络调试助手࿰…...
LeetCode回溯算法的解题思路
回溯法概念 回溯法:一种通过探索所有可能的候选解来找出所有的解的算法。如果候选解被确认不是一个解(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化抛弃该解,即回溯并且再次尝试。 应用场景 回溯算…...

泰克示波器(TBS2000系列)数学运算功能使用
目录 1 数学运算菜单1.1 运算符选择1.2 信源选择1.3 数学运算结果 1 数学运算菜单 Math运算按钮,用于实现对两个通道的信号进行实时的“加、减、乘”运算,计算时信源1在前面,信源2在运算符的右边,设置时设置信源与运算符就行了。…...

数据结构与算法之美学习笔记:50 | 索引:如何在海量数据中快速查找某个数据?
目录 前言为什么需要索引?索引的需求定义构建索引常用的数据结构有哪些?总结引申 前言 本节课程思维导图: 在第 48 节中,我们讲了 MySQL 数据库索引的实现原理。MySQL 底层依赖的是 B 树这种数据结构。留言里有同学问我ÿ…...

Python(SQLite)executescript用法
SQLite 数据库模块的游标对象还包含了一个 executescript() 方法,这不是一个标准的 API 方法,这意味着在其他数据库 API 模块中可能没有这个方法。但是这个方法却很实用,它可以执行一段 SQL 脚本。 例如,如下程序使用 executescr…...

BUUCTF-Real-[ThinkPHP]IN SQL INJECTION
目录 漏洞描述 漏洞分析 漏洞复现 漏洞描述 漏洞发现时间: 2018-09-04 CVE 参考:CVE-2018-16385 最高严重级别:低风险 受影响的系统:ThinkPHP < 5.1.23 漏洞描述: ThinkPHP是一款快速、兼容、简单的轻量级国产P…...
python安装步骤
安装 Python 的步骤如下: 在 Python 官方网站(https://www.python.org)上下载 Python 安装程序。运行下载的安装程序。在安装程序中选择要安装的 Python 版本(通常选择最新版本),并选择安装目录。确保勾选…...

BlueLotus 下载安装使用
说明 蓝莲花平台BlueLotus,是清华大学曾经的蓝莲花战队搭建的平台,该平台用于接收xss返回数据。 正常执行反射型xss和存储型xss: 反射型在执行poc时,会直接在页面弹出执行注入的poc代码;存储型则是在将poc代码注入用…...
.[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
导言: 在当今数字化时代,勒索病毒已成为网络安全领域的一大威胁。其中一种新近出现的勒索病毒是由[hudsonLcock.li].mkp[hendersoncock.li].mkp[myersairmail.cc].mkp制作的,它以其高效的加密算法和勒索方式而备受关注。本文91数据恢复将介绍…...

基于SpringBoot和PostGIS的震中影响范围可视化实践
目录 前言 一、基础数据 1、地震基础信息 2、全国行政村 二、Java后台服务设计 1、实体类设计 2、Mapper类设计 3、控制器设计 三、前端展示 1、初始化图例 2、震中位置及影响范围标记 3、行政村点查询及标记 总结 前言 地震等自然灾害目前还是依然不能进行准确的预…...

JUnit实践教程——Java的单元测试框架
前言 大家好,我是chowley,最近在学单元测试框架——JUnit,写个博客记录一下! 在软件开发中,单元测试是确保代码质量和稳定性的重要手段之一。JUnit作为Java领域最流行的单元测试框架,为开发人员提供了简单…...

选择大语言模型:2024 年开源 LLM 入门指南
作者:来自 Elastic Aditya Tripathi 如果说人工智能在 2023 年起飞,这绝对是轻描淡写的说法。数千种新的人工智能工具被推出,人工智能功能被添加到现有的应用程序中,好莱坞因对这项技术的担忧而戛然而止。 甚至还有一个人工智能工…...

ElastAlert 错误日志告警
文章目录 前言一、ElastAlert 概览1.1 简介1.2 ElastAlert 特性 二、ElastAlert 下载部署2.1 安装 Python3 环境2.2 下载 ElastAlert2.3 部署 ElastAlert 三、接入平台3.1 对外接口层3.2 服务层 前言 ElastAlert 是 Yelp 公司基于 python 开发的 ELK 日志告警插件,…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...