caffe可重入单例机制分析
一个函数可重入是指该函数可以被多个线程同时调用。大多数函数都不是可重如的,因为很多函数会修改静态数据结构里的内容,如果多个线程同时调用,势必破坏共享的静态结构。可以在不改变公共接口的情况下,将一个非重入函数修改为可重入函数。思想是使用线程的本地存储来实现,而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可重入单例机制分析的更多相关文章
- Java 重入锁 ReentrantLock 原理分析
1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生 ...
- 【分布式锁】06-Zookeeper实现分布式锁:可重入锁源码分析
前言 前面已经讲解了Redis的客户端Redission是怎么实现分布式锁的,大多都深入到源码级别. 在分布式系统中,常见的分布式锁实现方案还有Zookeeper,接下来会深入研究Zookeeper是 ...
- IOS 单例崩溃分析 2014-12-10 15:46:36
单例模式是常用的模式,但是在单例应用中偶或引发崩溃让人匪夷所思.其实真的是单例引起的吗?未必.但是现象都指向了是单例引起的.今天我亲身经历了看似崩溃在单例上的一个例子,但实则不是,今天做个记录用于今后 ...
- malloc的可重入性和线程安全分析
malloc函数是一个我们经常使用的函数,如果不对会造成一些潜在的问题.下面就malloc函数的线程安全性和可重入性做一些分析. 我们知道一个函数要做到线程安全,需要解决多个线程调用函数时访问共享资源 ...
- 可重入排他锁ReentrantLock源码浅析
1.引子 "ReentrantLock"单词中的“Reentrant”就是“重入”的意思,正如其名,ReentrantLock是一个支持重入的排他锁,即同一个线程中可以多次获得同步 ...
- C#中Timer使用及解决重入问题
C#中Timer使用及解决重入问题 ★介绍 首先简单介绍一下timer,这里所说的timer是指的System.Timers.timer,顾名思义,就是可以在指定的间隔是引发事件.官方介绍在这里,摘抄 ...
- 使用timer定时器,防止事件重入
首先简单介绍一下timer,这里所说的timer是指的System.Timers.timer,顾名思义,就是可以在指定的间隔是引发事件.官方介绍在这里,摘抄如下: 1 2 Timer 组件是基于服务器 ...
- [转]C#中Timer使用及解决重入问题
本文转自:http://www.cnblogs.com/hdkn235/archive/2014/12/27/4187925.html ★前言 打开久违的Live Writer,又已经好久没写博客了, ...
- unity单例封装
# 1.前言本篇主要针对Unity单例模式,完成一个可以重复继承使用的抽象类,减少重复的工作与代码.同时,对存在的多种单例进行优劣分析.# 2.Unity单例问题分析## 2.1 单例原则单例要满足以 ...
随机推荐
- Shell学习之条件测试(四)
Shell学习之条件测试 目录 逻辑测试 文件测试 数值比较 字符串比较 逻辑测试 格式: [ 表达式 ] 操作符 [ 表达式2 ] …… 命令1 操作符 命令2 …… 常用的操作符 ( 注意:-a和 ...
- [ 高危 ]mt某站SQL注入
RANK 24 金币 24 等价RMB 240 与上一漏洞同源所以只有24 数据包: GET /check?clientId=64915 HTTP/1.1 Host: xxx.meituan. ...
- Linux学习笔记9
管道 pipe 如 : ls |less -MN 含义把ls 结果输出到less ls=|=more ls 命令 ls -a 展示隐藏的文件 隐藏文件一般以.开始 ls -t 以时间戳排序 ls - ...
- WPF DataGrid 每行ComboBox 内容不同的设置方法
<toolkit:DataGridComboBoxColumn x:Name="DgCbcSignal" Header="信号源" SelectedIte ...
- 2018 EC-Final 部分题解 (A,J)
目录 The 2018 ICPC Asia-East Continent Final A.Exotic - Ancient City(思路 并查集) J.Philosophical - Balance ...
- Java笔记(八)TreeMap & TreeSet & LinkedHashMap
TreeMap & TreeSet & LinkedHashMap 一.TreeMap HashMap缺陷:键值对之间没有特定的顺序.在TreeMap中, 键值对之间按键有序,Tree ...
- git 撤销更改的文件
在没有git add之前: 1.撤销所有更改:git checkout . 2.撤销指定文件的更改:git checkout -- file.txt git add之后: git reset HEAD ...
- python网络编程(十二)
协程 协程,又称微线程,纤程.英文名Coroutine. 协程是啥 首先我们得知道协程是啥?协程其实可以认为是比线程更小的执行单元. 为啥说他是一个执行单元,因为他自带CPU上下文.这样只要在合适的时 ...
- URL结构
一.概念 URL:统一资源定位符 (Uniform Resource Locator, URL). 完整的URL由这几个部分构成:scheme://host:port/path?query#hash: ...
- 学习Struts--Chap02:Struts2框架各个功能模块和程序执行流程的介绍
1.Struts2的系统架构: 2.架构中不同Key的作用介绍: servlet Filters:过滤器链,client的全部请求都要经过Filter链的处理. Struts Core:Struts2 ...