怎么制作网站论坛模板,图片制作在线生成器免费版,自学平面设计入门教程,网站公司市场营销方案1 线程和进程的区别 资源分配和调度#xff1a; 进程#xff08;火车#xff09;是操作系统进行资源分配和调度的最小单位。它有自己的独立资源空间#xff0c;包括内存、文件句柄等。线程#xff08;车厢#xff09;是CPU调度的最小单位。一个进程可以包含多个线程…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.o2.2.2 Makefile编译
但是如果用Makefile一堆文件编译的情况下如何设置
# Makefile中变量定义如:标签内容,后面的变量引用需要$(标签)
GPU0
CUDNN0
OPENCV0
OPENMP0 # OpenMP是一套支持跨平台共享内存方式的多线程并发的编程API
DEBUG0ARCH -gencode archcompute_30,codesm_30 \-gencode archcompute_35,codesm_35 \-gencode archcompute_50,code[sm_50,compute_50] \-gencode archcompute_52,code[sm_52,compute_52]
# -gencode archcompute_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 archcompute_52,codecompute_52VPATH./src/:./examples
SLIBlibdarknet.so #待生成的动态链接库
ALIBlibdarknet.a #待生成的静态链接库
EXECdarknet #待生成的执行文件名称
OBJDIR./obj/ #生成目标文件的目录即当期目录下obj子目录CCgcc
CPPg
NVCCnvcc #nvidia编译器
ARar #arLinux系统的一个备份压缩命令用于创建、修改备存文件archive。这里的ar命令是将目标文件打包为静态链接库。
ARFLAGSrcs #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表示需要生成的目标文件
OBJgemm.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
EXECOBJAcaptcha.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
OBJconvolutional_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