大多数函数都不是可重入的。这也就是说在某一个线程已经调用了一个函数时,如果你再调用同一个函数,那么这样是不安全的。举例来说,std::strtok就是不可重入的,因为它使用静态变量来保存要被分割成符号的字符串。

函数原型:char *strtok(char *s,const char *delim)

函数功能:分解字符串为一组字符串,s为要分解的字符串,delim为分隔字符串

描述:strtok()用来将字符串分割成一个个片段,参数s指向将要被分隔的字符串,参数delim则为分隔字符串,当strtok()在参数s的字符串中发现到参数delim的分隔字符时,则会将该字符改为'\0'字符,在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL.每次调用成功则返回被分隔片段的指针。


#include <iostream>   
#include <cstring>   
using namespace std;   
int main()   
{   char sentence[]="This is a sentence with 7 tokens";  cout<<"The string to be tokenized is:\n"<<sentence<<"\n\nThe tokens are:\n\n"; char *tokenPtr=strtok(sentence," "); while(tokenPtr!=NULL) {   cout<<tokenPtr<<'\n';   tokenPtr=strtok(NULL," ");   } cout<<"After strtok, sentence = "<<sentence<<endl;   return 0;   

/* 函数第一次调用需设置两个参数。第一次分割的结果,返回串中第一个 ',' 之前的字符串,也就是上面的程序第一次输出abc。   
 * 第二次调用该函数strtok(NULL,","),第一个参数设置为NULL。结果返回分割依据后面的字串,即第二次输出d。   
 * strtok是一个线程不安全的函数,因为它使用了静态分配的空间来存储被分割的字符串位置   
 * 线程安全的函数叫strtok_r,ca   
 * 运用strtok来判断ip或者mac的时候务必要先用其他的方法判断'.'或':'的个数,
 * 因为用strtok截断的话,比如:"192..168.0...8..."这个字符串,strtok只会截取四次,中间的...无论多少都会被当作一个key
 */

上面内容引用自:https://blog.csdn.net/luciazzzz/article/details/38538033

一个不可重入的函数通过连续的调用来保存静态变量或者是返回一个指向静态数据的指针,有两种方法可以让不可重用的函数变成可重用的函数。

方法1:就是改变接口,用指针或引用代替原先使用静态数据的地方。比方说,POSIX定义了strok_r,std::strtok中的一个可重入的变量,它用一个额外的char**参数来代替静态数据。这种方法很简单,而且提供了可能的最佳效果。但是这样必须改变公共接口,也就意味着必须改代码。

方法2:不用改变公有接口,而是用本地存储线程(Thread-Locally Storage)来代替静态数据(有时也被成为特殊线程存储,thread-specific storage)。

Boost线程库提供了智能指针boost::thread_specific_ptr来访问本地存储线程。thread_specific_ptr线程局部存储的包装,它可用于封装线程独立的全局变量。每一个线程第一次使用这个智能指针的实例时,它的初值是NULL(所以必须要先检查这个它的值是否为空),在每个线程使用它之前需要new一个对象交给全局的threah_specific_ptr进行管理,当线程退出后,Boost线程库保证本地存储线程中保存的数据会在线程结束后被清除,这样,各个线程就可以各自独立地访问这个全局变量的本地存储版本,线程之间就不会因为访问同一全局对象而引起资源竞争导致性能下降。而线程结束时,这个资源会被自动释放。

它可以应用在以下两种场景:

1. 改编一个原本设计用于单线程的库接口,比如libc里的strtok函数。这种库一般隐含的使用一个全局变量,可以使用thread_specific_ptr控制全局变量,使其可用于多线程。
       2. 线程中使用了一系列的方法/函数,它们需要一个逻辑上的全局变量来共享数据,但实际上这个变量是线程独立的。

thread_specific_ptr代表了某个全局变量的本地存储,各个线程可以各自独立地通过它访问这个全局变量的本地副本,起到了井水不犯河水的效果。

使用boost::thread_specific_ptr的简单例子。

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/tss.hpp>
#include <iostream>boost::mutex io_mutex;
boost::thread_specific_ptr<int> ptr;struct count
{count(int id) : id(id) { }void operator()(){if (ptr.get() == 0)ptr.reset(new int(0));for (int i = 0; i < 10; ++i){(*ptr)++;boost::mutex::scoped_locklock(io_mutex);std::cout << id << ": "<< *ptr << std::endl;}}int id;
};int main(int argc, char* argv[])
{boost::thread thrd1(count(1));boost::thread thrd2(count(2));thrd1.join();thrd2.join();return 0;
}

其中创建了两个线程来初始化本地存储线程,并有10次循环,每一次都会增加智能指针指向的值,并将其输出到std::cout上(由于std::cout是一个共享资源,所以通过互斥体进行同步)。main线程等待这两个线程结束后就退出。从这个例子输出可以明白的看出每个线程都处理属于自己的数据实例,尽管它们都是使用同一个boost::thread_specific_ptr。

参考:

https://blog.csdn.net/liujiayu2/article/details/50587084

https://blog.csdn.net/flyingleo1981/article/details/47083737

boost库中thread多线程中的thread_specific_ptr相关推荐

  1. 【Boost】boost库中thread多线程详解1——thread入门与简介

    1. 概述 线程就是,在同一程序同一时间内允许执行不同函数的离散处理队列. 这使得一个长时间去进行某种特殊运算的函数在执行时不阻碍其他的函数变得十分重要. 线程实际上允许同时执行两种函数,而这两个函数 ...

  2. 5002.boost库之thread

    最近学习 boost库,网上讲了很多的他的优势,跨平台.线程安全等 ,下面 咱们来看如何直接实现的吧. /*********************************************** ...

  3. 19.Qt中Thread线程中创建QTcpSocket

    Thread线程中创建QTcpSocket 本文承接上一篇博文,Qt线程创建,本文记录在线程中创建socket 套接字,连接服务器进行编程. /**************************** ...

  4. JAVA中stacksize是什么意思_【Java Thread StackSize】如何理解Java中Thread构造器中的stackSize的默认值为0?...

    Thred的stackSize默认值 e-mail:rolltion.zhang@foxmail.com 前言:为什么要研究默认值 在Java和Java开发框架中,我们经常会遇到一系列的默认值,尽管他 ...

  5. 【Boost】boost库中thread多线程详解9——thread_specific_ptr线程局部存储

    大多数函数都不是可重入的.这也就是说在某一个线程已经调用了一个函数时,如果你再调用同一个函数,那么这样是不安全的.一个不可重入的函数通过连续的调用来保存静态变量或者是返回一个指向静态数据的指针. 举例 ...

  6. 【Boost】boost库中thread多线程详解5——谈谈线程中断

    线程不是在任意时刻都可以被中断的.如果将线程中函数中的sleep()睡眠等待去掉,那么即使在主线程中调用interrupt()线程也不会被中断.thread库预定义了若干个线程的中断点,只有当线程执行 ...

  7. 【Boost】boost库中thread多线程详解13——线程标识符

    在boost中也有唯一标识线程的数据结构:thread::id. boost::thread thread_func(func); thread::id var_id = thread_func.ge ...

  8. 【Boost】boost库中thread多线程详解12——线程的分离与非分离

    Boos::thread线程的默认属性为非分离状态,线程结束后线程标识符.线程退出状态等信息需要通过join方法回收. boost::thread thread_func(func); thread_ ...

  9. 【Boost】boost库中thread多线程详解11——线程的休眠和中断

    boost::thread 中提供一个静态方法 void boost::thread::sleep(system_time const& abs_time); 线程将休眠直到时间超时. sle ...

  10. 【Boost】boost库中thread多线程详解10——condition条件变量

    有的时候仅仅依靠锁住共享资源来使用它是不够的.有时候共享资源只有某些状态的时候才能够使用.比方说,某个线程如果要从堆栈中读取数据,那么如果栈中没有数据就必须等待数据被压栈.这种情况下的同步使用互斥体是 ...

最新文章

  1. [转]Effective C# 原则5:始终提供ToString()
  2. 嵌入式linux开发课程设计,嵌入式Linux开发课程设计指导书
  3. 计算机网络管理员适用单位,计算机网络管理员软考理论复习题(附答案).(40页)-原创力文档...
  4. python学生管理系统用类写_python面向对象——学校学生教职工管理系统类的实例...
  5. 外媒:美国做空机构浑水放弃做空特斯拉
  6. Iptables(2) - iptables命令的基本用法
  7. 计算机网络 教学大纲 谢希仁,《计算机网络》教学大纲.doc
  8. [转载] python定义整型常量_Python笔记——数据类型、变量和常量
  9. SQL语句学习之路7
  10. PHP包含文件函数include、include_once、require、require_once区别和总结
  11. WEB前端开发快速入门教程
  12. CPU内部架构与工作原理
  13. 软件测试找游戏bug,游戏测试用例及游戏测试bug详解
  14. 【OpenCV学习笔记】之离散傅里叶变换(DFT)
  15. 【项目实战】传智健康
  16. OPNET网络仿真分析-前言
  17. gulp-less解决遇到错误停止执行task
  18. 【老孙随笔】腾讯,互联网创业者的噩梦
  19. esp32c3 crash分析
  20. vb数据库编程(三)--SQL语言

热门文章

  1. 【php】相对路径/绝对路径报错?
  2. 2022年低功耗软路由cpu一览
  3. 从零配置腾讯云cdn加速服务!
  4. 如何认识会计科目,看懂财务报表
  5. 企业网站建设要点和推广方法有哪些?
  6. 如何在Mac上清理磁盘空间?
  7. C罗是你人生中最好的健身教练和精神导师
  8. 云痕大数据 家长登录_云痕大数据查成绩app
  9. 利用官方预训练模型快速计算Inception Score和FID
  10. Saved Blogs