Linux多线程可重入函数

 Reentrant和Thread-s     afe    

在单线程程序中,整个程序都是顺序执行的,一个函数在同一时刻只能被一个函数调用,但在多线程中,由于并发性,一个函数可能同时被多个函数调用,此时这个函数就成了临界资源,很容易造成调用函数处理结果的相互影响,如果一个函数在多线程并发的环境中每次被调用产生的结果是不确定的,我们就说这个函数是"不可重入的"/"线程不安全"的。为了解决这个问题,POSIX多线程库提出了一种机制,用来解决多线程环境中的线程数据私有化问题,这套机制的主要思想是利用同步和互斥维护一个同名不同值的表,这个表会维护每个线程自己的资源地址,表面上是同一个变量,实质上这个变量在不同的线程中的地址是不一样,这样就保证了每个线程其实都在使用自己的资源,实现了"thread-safe"。
其实,随着多线程程序的逐渐流行,除了这种利用系统机制保护线程私有数据的方法,还有一部分人重新编写了一些多线程库函数,这些函数的主要特点就是实现了算法和数据的分离,函数内部只负责实现算法,需要的数据由线程传入,这样就保证了函数的多线程安全,eg

char *asc     ti   me(const struct tm *tm);char *asc  TI me_r(const struct tm *tm, char *buf); //这个就是asc  TI me的thread-safe版,有_r后缀

但由于接口不同,完全重写的函数推广尚需时日。
当下用的更多的是使用_REENTRANT来在原来的函数的基础上改造,如果编译的时候定义了这个宏,相关的库函数就会被编译成"thread-safe"的版本。

模型

如果要查看这些函数的man手册,可以安装相关的man手册

pthread_key_t key //创建用于保护线程私有资源的keypthread_once_t once_key //创建用于初始化key的once_key,要求用PTHREAD_INIT_ONCE来赋值,否则结果不确定pthread_key_crea     te   () //创建keypthread_once() //初始化keypthread_getspedifc() //从key表中获得线程私有资源的地址pthread_setspedifc() //将线程私有资源的地址放到key中...

例子

表面上每个函数调用了reve     rs   e()都会得到rev的地址,其实这个rev地址在不同的线程中并不相同,一旦一个线程调用了reverse()函数,函数首先会到key标识的表中去搜索这个线程以前是否调用过这个函数,如果调用过,就将表中属于这个线程的rev地址返回,如果没有,就分配rev,并将该线程和它的专属rev地址注册到表中,这样就把reverse()打造成了一个可重入的函数。

#include#include#include#includepthread_key_t key;pthread_once_t once_key=PTHREAD_ONCE_INIT;#ifdef _REENTRANTvoid myDestructor(void*p){ free(p);}void myCreateKey(void){ //创建key pthread_key_create(&key,myDestructor);}#endifchar* reverse(char* buf,int len){#ifdef _REENTRANT //初始化key pthread_once(&once_key,myCreateKey); //从key中获取一个thread-specific的数据 char* rev=(char*)pthread_getspecific(key); if(NULL==rev){ rev=(char*)malloc(len+1); //将thread-specific的数据放到key中 pthread_setspecific(key,rev); }#else sta  TI c char rev[100];#endif bzero(rev,sizeof(rev)); //翻转buf while(len--) rev[len]=*buf++; return rev;}void* fcn1(void* p){ while(1){ char buf[100]="123456789"; printf("[%lu]:%s\n",pthread_self(),buf); char* rev=reverse(buf,strlen(buf)); sleep(1); printf("[%lu]:%s\n",pthread_self(),rev); }}void* fcn2(void* p){ while(1){ char buf[100]="abcdef"; printf("[%lu]:%s\n",pthread_self(),buf); char* rev=reverse(buf,strlen(buf)); sleep(2); printf("[%lu]:%s\n",pthread_self(),rev); }}int m     ai   n(int argc, const char *argv[]){ pthread_t  TI d[4]; pthread_create(&tid[0],NULL,fcn1,NULL); pthread_create(&tid[1],NULL,fcn2,NULL); pause(); return 0;}

Linux多线程可重入函数_设计制作_测量仪表
35
145
0
2

相关资讯

  1. 1、从网剧十年迭代升级,看一众平台沉浮兴衰2987
  2. 2、《俄囧》?《囧妈》?徐峥自导自演《囧3》明年1月1月开拍3779
  3. 3、谢楠首晒唐嫣大婚喜糖,包装华丽,里面放了一张照片,好有创意3784
  4. 4、斯图尔特神还原戴安娜王妃!《斯宾塞》曝片场照832
  5. 5、金刚川大爆后战狼3马上拍?吴京直接否认,道出没开机的关键难处_电影4673
  6. 6、韩寒餐厅多家门店倒闭还被官司缠身,网友:做生意不如写文章在行4577
  7. 7、爷孙恋?又一港姐找到好归宿,“宫女”罗霖被曝秘嫁66岁高层3486
  8. 8、朱一龙《无限深度》杀青,预计暑假上映268
  9. 9、动画电影论坛首举办美影厂长:打造悟空成超级英雄4411
  10. 10、《狗十三》——你见过真正的大人吗?1710
全部评论(0)
我也有话说
0
收藏
点赞
顶部