您的位置首页>企业动态>

Linux 多线程可重入函数

导读 大家好,我是极客范的本期栏目编辑小友,现在为大家讲解Linux 多线程可重入函数问题。可重入和线程安全的在单线程程序中,整个程序是按顺

音频解说

大家好,我是极客范的本期栏目编辑小友,现在为大家讲解Linux 多线程可重入函数问题。

可重入和线程安全的

在单线程程序中,整个程序是按顺序执行的,一个函数只能同时被一个函数调用。然而,在多线程中,由于并发性,一个函数可能同时被多个函数调用。这时这个函数就变成了关键资源,很容易导致调用函数的处理结果相互影响。如果一个函数在多线程并发环境中的每次调用结果都是不确定的,我们就说这个函数是‘不可重入’/为了解决这个问题,POSIX多线程库提出了一种机制来解决多线程环境中线程数据私有化的问题。这种机制的主要思想是使用同步和互斥来维护一个同名不同值的表。该表将维护每个线程自己的资源地址。表面上看,是同一个变量。事实上,这个变量在不同线程中的地址是不同的,从而确保每个线程实际上使用自己的资源,实现“线程安全”。

事实上,随着多线程程序的普及,除了这种利用系统机制保护线程私有数据的方法外,还有人重写了一些多线程库函数。这些功能的主要特点是算法和数据的分离。函数只负责内部实现算法,所需数据由线程传入,从而保证函数的多线程安全性,例如。

char * ASC time(const struct TM * TM);char * AsCtime _ r(const struct TM * TM,char * buf);//这是后缀为_ r的ascTIme的线程安全版本。

但是由于接口的不同,完全重写的功能普及还需要一段时间。

目前,我们使用_ REENTRANT来转换原始函数。如果这个宏是在编译时定义的,相关的库函数将被编译成“线程安全”版本。

模型

如果想查看这些功能的手册,可以安装相关的手册。

Pthread_key_t key //创建一个用于保护线程私有资源的密钥pthread _ once _ once创建一次_key用于初始化密钥,需要给PTHREAD_INIT_ONCE赋值。否则结果不确定:pthread _ key _ Create()//Create key thread _ once()//Initialize key thread _ getspedifc()//从密钥表中获取线程私有资源pthread _ setspedifc()的地址//将线程私有资源的地址放入密钥中。

例子

表面上看,每个调用reverse()的函数都会得到rev的地址,实际上,这个rev地址在不同的线程中是不一样的。一旦某个线程调用了reverse()函数,该函数将首先转到由key标记的表中,以搜索该线程之前是否调用过该函数。如果有,它将返回属于表中这个线程的rev地址。如果没有,它将分配rev,并在表中注册这个线程及其独占Rev地址,以便放置Revere。

# include # include # include # include thread _ key _ t key;PTHREAD _ ONCE _ t ONCE _ key=PTHREAD _ ONCE _ INIT;# ifdef _ re entranvoid myDestructor(void * p){ free(p);} void myCreateKey(void){//Create key thread _ key _ Create(key,我的毁灭者);} # endifchar * reverse (char * buf,int len){ # ifdef _ recent//initialize key thread _ once(once _ key,my create key);//从键中获取线程特定的数据char * rev=(char *)pthread _ getspecific(键);if(NULL==rev){ rev=(char *)malloc(len 1);//将线程特定的数据放入key pthread_setspecific(key,rev)中;} # else STATic char rev[100];#endif bzero(rev,sizeof(rev));//flip buf while(len-)rev[len]=* buf;返回版本;} void * fcn 1(void * p){ while(1){ char buf[100]=' 123456789 ';printf('[%lu]:%s\n ',pthread_self(),buf);char* rev=reverse(buf,strlen(buf));睡眠(1);printf('[%lu]:%s\n ',pthread_self(),rev);} } void * fcn 2(void * p){ while(1){ char buf[100]=' abcdef ';printf('[%lu]:%s\n ',pthread_self(),buf);char* rev=reverse(buf,strlen(buf));睡眠(2);printf('[%lu]:%s\n ',pthread_self(),rev);}}int main(int argc,const char * argv[]){ pthread _ t TiD[4];pthread_create(tid[0],NULL,fcn1,NULL);pthread_create(tid[1],NULL,fcn2,NULL);pause();返回0;}

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。