一个函数可重入是指该函数可以被多个线程同时调用。大多数函数都不是可重如的,因为很多函数会修改静态数据结构里的内容,如果多个线程同时调用,势必破坏共享的静态结构。可以在不改变公共接口的情况下,将一个非重入函数修改为可重入函数。思想是使用线程的本地存储来实现,而boost::thread_specific_ptr正好提供了使用TLS(thread local storage)的机制。

在caffe框架中,class Caffe是一个单例类,这个类是可以重入的,即可以被多个线程同时使用:

进入到上图109行的Get()函数:

这个函数是一个static的函数,它的返回值是Caffe对象的引用,第13行定义了一个指向Caffe对象的智能指针,类型为boost::thread_specific_ptr<Caffe>.代码的16行首先判断thread_instance_智能指针指向的对象是否为空,如果为空则说明进入到这个函数的线程是第一次运行这个函数,那么就执行17行,重新new一个caffe对象,这个对象是属于该线程独有的,存放在该线程的TLS(Thread local storage)中。如果thread_instance_智能指针指向的对象不为空,说明进入到这个函数的线程已经不是第一次运行到这行代码了,那么就直接将自己TLS中的Caffe对象拿来使用就行了。boost::thread_specific_ptr中Get()函数的定义如下图82行所示:

这个函数其实就是返回线程私有存储空间中的对象而已。

可以用下面的示例代码来验证boost::thread_specific_ptr的机制:

#include <iostream>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/tss.hpp> 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_lock lock(io_mutex);
std::cout << id << ": " << *ptr << std::endl;
}
}
int id; }; int main() {
boost::thread thrd1(count(1));
boost::thread thrd2(count(2));
thrd1.join();
thrd2.join();
return 0;
}

这段代码声明了一个指向int类型的智能指针,main函数中使用了两个线程来访问该ptr,每个线程都会对ptr指向的值执行加法操作,从输出结果可以看到,两个线程的值互不干扰:

该代码采用cmake编写,完整的工程项目点击这里

caffe可重入单例机制分析的更多相关文章

  1. Java 重入锁 ReentrantLock 原理分析

    1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生 ...

  2. 【分布式锁】06-Zookeeper实现分布式锁:可重入锁源码分析

    前言 前面已经讲解了Redis的客户端Redission是怎么实现分布式锁的,大多都深入到源码级别. 在分布式系统中,常见的分布式锁实现方案还有Zookeeper,接下来会深入研究Zookeeper是 ...

  3. IOS 单例崩溃分析 2014-12-10 15:46:36

    单例模式是常用的模式,但是在单例应用中偶或引发崩溃让人匪夷所思.其实真的是单例引起的吗?未必.但是现象都指向了是单例引起的.今天我亲身经历了看似崩溃在单例上的一个例子,但实则不是,今天做个记录用于今后 ...

  4. malloc的可重入性和线程安全分析

    malloc函数是一个我们经常使用的函数,如果不对会造成一些潜在的问题.下面就malloc函数的线程安全性和可重入性做一些分析. 我们知道一个函数要做到线程安全,需要解决多个线程调用函数时访问共享资源 ...

  5. 可重入排他锁ReentrantLock源码浅析

    1.引子 "ReentrantLock"单词中的“Reentrant”就是“重入”的意思,正如其名,ReentrantLock是一个支持重入的排他锁,即同一个线程中可以多次获得同步 ...

  6. C#中Timer使用及解决重入问题

    C#中Timer使用及解决重入问题 ★介绍 首先简单介绍一下timer,这里所说的timer是指的System.Timers.timer,顾名思义,就是可以在指定的间隔是引发事件.官方介绍在这里,摘抄 ...

  7. 使用timer定时器,防止事件重入

    首先简单介绍一下timer,这里所说的timer是指的System.Timers.timer,顾名思义,就是可以在指定的间隔是引发事件.官方介绍在这里,摘抄如下: 1 2 Timer 组件是基于服务器 ...

  8. [转]C#中Timer使用及解决重入问题

    本文转自:http://www.cnblogs.com/hdkn235/archive/2014/12/27/4187925.html ★前言 打开久违的Live Writer,又已经好久没写博客了, ...

  9. unity单例封装

    # 1.前言本篇主要针对Unity单例模式,完成一个可以重复继承使用的抽象类,减少重复的工作与代码.同时,对存在的多种单例进行优劣分析.# 2.Unity单例问题分析## 2.1 单例原则单例要满足以 ...

随机推荐

  1. 初心不负 笔记-JS高级程序设计-引用类型篇-Array

    ES3方法集合: 1join()方法,将一个数组里面的所有元素转换成字符串,然后再将他们连接起来返回一个字符串,通过制定的符号,默认值为逗号.不会改变原数组 ,,,,]; a.join(); &quo ...

  2. Javascript你必须要知道的面试题

    1.使用 typeof bar === "object" 判断 bar 是不是一个对象有神马潜在的弊端?如何避免这种弊端? 使用 typeof 的弊端是显而易见的(这种弊端同使用 ...

  3. Nginx 反向代理 -- 一路上的坑

    前些天刚过来新公司上班,公司的项目都挺多的,只不过项目都是第三方公司团队开发的,现在本公司要组建自己的团队,我作为一个Java后台人员去接手第三方公司的全部项目,我已经是直接崩溃了(先解释一下我崩溃的 ...

  4. ppt字体

    字体也需要设计.  太大众不太好.   ppt自带的字体样式 有毛笔风格的.vrinda. 其他的和这个字体样式差不多.选其中一个就可以了. 其他的个性样式就需要下载字体扩展了.作为经常做ppt的,还 ...

  5. 用STM32CudeMX 点亮红色LED灯(软件操作步骤为主)

    1.收获如何使用软件STM32CudeMX配置代码 注意:自己要敲的代码,直接看102行,其他是软件配置的.!!! /** ************************************** ...

  6. Scrapy 使用CrawlSpider整站抓取文章内容实现

    刚接触Scrapy框架,不是很熟悉,之前用webdriver+selenium实现过头条的抓取,但是感觉对于整站抓取,之前的这种用无GUI的浏览器方式,效率不够高,所以尝试用CrawlSpider来实 ...

  7. 修改mybatis plus Generator模板生成字段注释枚举常量

    修改mybatis plus Generator模板生成字段注释枚举常量 本文基于最新的mybatis-plus 3.0.1版本源码修改,如果使用其它版本,处理方式也类似,主要是生成Entity的Fr ...

  8. Ubuntu下使用cmake生成可执行文件

    1.单个CPP文件的cmake 首先编写一个简单的程序(main.cpp): #include <iostream> using namespace std; int main() { c ...

  9. android Resources 类的使用

    使用 R.<resource_type>.<resource_name> 获取的是资源的一个 id (int 类型), 但有时候我们需要获取资源本身,这时候我们可以通过 Res ...

  10. linux重新设置密码,亲试成功

    1:进入/etc/my.cnf 在[mysqld]下添加一行skip-grant-tables 2:保存配置文件后,输入whereis systemctl(提示redirecting to 某个目录下 ...