APUE: 线程相关库函数

本文详细介绍了线程编程的基础知识,包括线程的概念、线程与进程的区别、线程的创建和管理,以及线程间的数据共享与独立等内容。此外还深入探讨了线程属性设置、线程同步和信号处理等高级主题。

线程有时称为轻权进程。


进程的所有信息对该进程的所有线程都是共享的。

每个线程有一个线程ID,线程ID只在它所属的进程环境中有效。


线程从进程继承的东西:

进程ID

地址空间

浮点环境

信号屏蔽字(不包括未决的信号集)


线程间共享的东西:

进程指令

大部分数据

信号处理程序和信号处理

当前工作目录

用户ID和组ID


线程间独立的东西:

线程ID

寄存器集合

errno

信号掩码

优先级


所有线程函数返回类型为int的成功返回0,失败返回错误码,不设置errno


线程编程需要链接库:

-lpthread


#####################################################

线程相关库函数

#####################################################

#include<pthread.h>


intpthread_create(

pthread_t*restrict thread,

//返回的线程ID

constpthread_attr_t *restrict attr,

//线程属性,NULL表示使用默认值

void*(*start_routine)(void*),

//线程启动函数,返回void*,只有一个参数void*

void*restrict arg

//如果参数不止一个,把这些参数放入一个结构,地址传给arg

);

创建线程,相当于fork;成功返回0,失败返回错误码,不设置errno

初始线程是程序开始执行时创建的主线程,其它线程是该函数创建的;线程创建时不能保证哪个线程先运行。


pthread_tpthread_self(void);

一个线程取得自己的线程ID,相当于getpid

返回调用线程的线程ID


intpthread_equal(pthread_ttid1, pthread_t tid2);

线程ID是一个结构pthread_t,如果两个线程ID相等返回非0,否则返回0.


intpthread_join(

pthread_tthread, //等待终止的线程ID

void**value_ptr

//如果非空,存放等待终止的线程的返回值;如果为空只是等待指定线程终止。

);

等待线程结束,相当于waitpid

调用线程是默认阻塞的,value_ptr用来存放退出状态,如果线程处于分离状态,函数返回EINVAL


intpthread_detach(pthread_tthread);

将指定线程设置为分离状态。

分离状态的线程底层存储资源可以在线程终止时立即被收回。


voidpthread_exit(void*value_ptr);

终止一个线程,相当于exit

value_ptr参数用来设置退出码,用pthread_join函数可以访问这个退出吗。

任一线程调用exit系列函数或向线程发送默认动作是终止的信号都可以终止整个进程。

正常终止线程方法:

1.最后一个线程从其启动例程返回

2.最后一个线程调用pthread_exit库函数

异常终止线程方法:

1.最后一个线程对取消请求做出响应


intpthread_cancel(pthread_tthread);

请求取消同一进程中的其它线程,并不等待线程终止。

相当于abort


voidpthread_cleanup_push(void(*routine)(void*),

//返回void*,参数也是void*

void*arg

//第二个参数是用来指定清理函数的更过参数

);

线程在下列情况调用清理函数routine

1.调用pthread_exit

2.调用pthread_cancel并响应

3.用非零参数调用pthread_cleanup_pop

清理函数通过这个函数入栈,先入栈的后执行。

相当于abexit


voidpthread_cleanup_pop(intexecute);

用来删除上次push的清理函数,如果execute=0那么还会禁止调用清理函数。


#####################################################

线程属性相关库函数

#####################################################

#include<pthread.h>


intpthread_attr_init(pthread_attr_t*attr);

初始化线程属性对象的结构attr


intpthread_attr_destory(pthread_attr_t*attr);

清理和回收初始化之后的线程属性结构attr


线程分离状态属性detachstate

intpthread_attr_getdetachstate(constpthread_attr_t *attr, int *detachstate);

把线程属性detachstate设置为下面值:

PTHREAD_CREATE_DETACHED:以分离状态启动线程

PTHREAD_CREATE_JOINABLE:正常启动线程


intpthread_attr_setdetachstate(pthread_attr_t*attr, int detachstate);

获取线程的属性detachstate值。


线程栈最低地址:

intpthread_attr_setstack(pthread_attr_t*attr, void *stackaddr, size_t stacksize);

可以同时管理stackaddrstacksize


intpthread_attr_getstack(pthread_attr_t*attr, void **stackaddr, size_t *stacksize);

读取stackaddrstacksize


线程栈的大小:

intpthread_attr_setstacksize(pthread_attr_t*attr, size_t stacksize);

设置stacksize


intpthread_attr_getstacksize(pthread_attr_t*attr, size_t stacksize);

读取stacksize


线程栈末尾的警戒缓冲区大小:

intpthread_attr_setguardsize(pthread_attr_t*attr, size_t guardsize);

guardsize=0表示不允许使用这种特征。


intpthread_attr_getguardsize(pthread_attr_t*attr, size_t guardsize);


取消选项:

intpthread_setcancelstate(intstate, int *oldstate);

调用线程取消函数并不等待线程终止,而是到达取消点就取消。

将取消状态设置为state,原来的放在oldstate

state

PTHREAD_CANCEL_ENABLE(线程启动时的默认取消状态)

PTHREAD_CANCEL_DISABLE:调用取消函数处于未决状态,当恢复为enable时在下一个取消点作用。


intpthread_setcanceltype(inttype, int *oldtype);

将取消类型设置为type,将原来的放在oldtype

type

PTHREAD_CANCEL_DEFERRED:延时取消:到取消点才取消(默认)

PTHREAD_CANCEL_ASYNCHRONOUS:异步取消:在任意时间取消


voidpthread_testcancel(void);

调用该函数自己设置取消点。


线程并发度:

intpthread_setconcurrency(intnew_level);

告诉系统我们希望并发运行多少线程。系统不一定采纳。

level=0可以撤销之前调用的set设置的level值,由系统自己决定并发度。


intpthread_getconcurrency(void);

返回当前的并发度。如果之前没有调用set设置该值函数返回0.


线程私有数据:

创建一个键,进程中的所有线程共用这个键,但是每个线程把这个键和不同的线程私有数据地址关联,创建新键时线程数据地址设为null。析构函数,当线程调用pthread_exit或返回时,正常退出析构函数就会被调用。


intpthread_key_create(pthread_key_tkeyp, void (*destructor)(void *));

创建一个键和一个析构函数。


intpthread_key_delete(pthread_key_t*key);

取消键与线程私有数据值之间的关联。


pthread_once_tinitflag = PTHREAD_ONCE_INIT

initflag是一个全局变量或静态变量。

intpthread_once(pthread_once_tinitflag,void (*initfn)(void));

该函数用来能保证initfn函数只被调用一次。


intpthread_setspecific(pthread_key_tkey, const void *value);

键创建之后,调用该函数把键和线程私有数据关联起来。


void*pthread_getspecific(pthread_key_tkey);

获取线程私有数据地址,返回线程私有数据,如果没有值与键关联返回NULL


线程和fork

在线程中调用fork之后子进程的线程继承了互斥量、读写锁和条件变量的状态。

intpthread_atfork(void(*prepare)(void), void (*parent)(void), void(*child)(void));

用来安装三个清理锁的函数。

prepare函数在fork调用之前调用获取父进程定义的所有锁;

parent函数在fork返回之前的父进程中调用,解锁prepare获取的所有锁;

child函数在fork返回之前的子进程中调用,解锁prepare获取的所有锁。


#####################################################

线程相关其它库函数

#####################################################

线程和信号:

成功int的函数成功返回0,失败返回错误码。


#include<signal.h>

intpthread_sigmask(inthow, const sigset_t *set, sigset_t *oldset);

用于多线程。

oldset如果非NULLoldset返回进程当前的信号屏蔽字。

set如果非NULL,根据how来修改set中的信号屏蔽字。

set如果为NULL,信号屏蔽字不变。


how:

SIG_BLOCK:阻塞,SIGKILLSIGSTOP不能阻塞。信号屏蔽字是当前信号屏蔽字和set的并集。设置阻塞后的信号进程不处理该信号,所以该信号是未决的。

SIG_UNBLOCK:解阻塞,信号屏蔽字是当前信号屏蔽字和set的补集的交集。

SIG_SETMASK:设置掩码,信号屏蔽字是set指向的信号集。


intsigwait(constsigset_t *set, int *sig);

等待一个或多个信号发生。

set是等待的信号集,sig指向的整数获取信号。


intpthread_kill(pthread_tthread, int signo);

把信号signo发送到线程thread


线程安全(重入):

如果一个函数在同一时刻被多个线程调用,就称这个函数是线程安全的,有一部分函数不能保证线程安全,也就是不可重入的,posix提供了这些函数的可重入版本(也就是带有_r的函数)。


#include<stdio.h>


intftrylockfile(FILE*fp);

成功返回0,失败返回非0.

锁定fp,但是不阻塞,如果别的线程已经锁定fp就返回。

voidflockfile(FILE*fp);

调用lock来锁定fp,别的线程不能使用fp。如果fp已经被别的线程锁定就阻塞。

voidfunlockfile(FILE*fp);

解锁fp,使别的线程能够使用fp


intgetchar_unlocked(void);

intgetc_unlocked(FILE*fp);

这两个函数成功返回下一个字符,到达文件结尾或出错返回EOF


intputchar_unlocked(intc);

intputc_unlocked(intc, FILE *fp);

这两个函数成功返回c,出错返回EOF


未完待续......


内容概要:本文介绍了ENVI Deep Learning V1.0的操作教程,重点讲解了如何利用ENVI软件进行深度学习模型的训练与应用,以实现遥感图像中特定目标(如集装箱)的自动提取。教程涵盖了从数据准备、标签图像创建、模型初始化与训练,到执行分类及结果优化的完整流程,并介绍了精度评价与通过ENVI Modeler实现一键化建模的方法。系统基于TensorFlow框架,采用ENVINet5(U-Net变体)架构,支持通过点、线、面ROI或分类图生成标签数据,适用于多/高光谱影像的单一类别特征提取。; 适合人群:具备遥感图像处理基础,熟悉ENVI软件操作,从事地理信息、测绘、环境监测等相关领域的技术人员或研究人员,尤其是希望将深度学习技术应用于遥感目标识别的初学者与实践者。; 使用场景及目标:①在遥感影像中自动识别和提取特定地物目标(如车辆、建筑、道路、集装箱等);②掌握ENVI环境下深度学习模型的训练流程与关键参数设置(如Patch Size、Epochs、Class Weight等);③通过模型调优与结果反馈提升分类精度,实现高效自动化信息提取。; 阅读建议:建议结合实际遥感项目边学边练,重点关注标签数据制作、模型参数配置与结果后处理环节,充分利用ENVI Modeler进行自动化建模与参数优化,同时注意软硬件环境(特别是NVIDIA GPU)的配置要求以保障训练效率。
内容概要:本文系统阐述了企业新闻发稿在生成式引擎优化(GEO)时代下的全渠道策略与效果评估体系,涵盖当前企业传播面临的预算、资源、内容与效果评估四大挑战,并深入分析2025年新闻发稿行业五大趋势,包括AI驱动的智能化转型、精准化传播、首发内容价值提升、内容资产化及数据可视化。文章重点解析央媒、地方官媒、综合门户和自媒体四类媒体资源的特性、传播优势与发稿策略,提出基于内容适配性、时间节奏、话题设计的策略制定方法,并构建涵盖品牌价值、销售转化与GEO优化的多维评估框架。此外,结合“传声港”工具实操指南,提供AI智能投放、效果监测、自媒体管理与舆情应对的全流程解决方案,并针对科技、消费、B2B、区域品牌四大行业推出定制化发稿方案。; 适合人群:企业市场/公关负责人、品牌传播管理者、数字营销从业者及中小企业决策者,具备一定媒体传播经验并希望提升发稿效率与ROI的专业人士。; 使用场景及目标:①制定科学的新闻发稿策略,实现从“流量思维”向“价值思维”转型;②构建央媒定调、门户扩散、自媒体互动的立体化传播矩阵;③利用AI工具实现精准投放与GEO优化,提升品牌在AI搜索中的权威性与可见性;④通过数据驱动评估体系量化品牌影响力与销售转化效果。; 阅读建议:建议结合文中提供的实操清单、案例分析与工具指南进行系统学习,重点关注媒体适配性策略与GEO评估指标,在实际发稿中分阶段试点“AI+全渠道”组合策略,并定期复盘优化,以实现品牌传播的长期复利效应。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值