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 单例原则单例要满足以 ...
随机推荐
- pymysql:Mysql拒绝从远程访问的解决办法
pymysql:Mysql拒绝从远程访问的解决办法 pymysql连接数据库 # 导入pymysql模块 import pymysql # 连接database conn = pymysql.conn ...
- Linux学习之RPM包管理-yum管理(十七)
Linux学习之RPM包管理-yum管理 目录 IP地址配置 网络yum源 yum命令 光盘yum源搭建 IP地址配置 IP+子网掩码就可以在局域网(内网)使用. IP+子网掩码+网关+DNS就可以访 ...
- 浅析js闭包
闭包是一个老生常谈的问题,简单概括下闭包的形成的两个条件: 1.定义在函数内部 2.函数内部引用父层作用域变量 举一个最简单的例子: function test() { var a = 1; func ...
- 在windows上安装redis并设置密码
在windows上安装redis Redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的Web应用程序的完美解决方案. Redis从它的许多竞争继承来的三个主要特点: Redi ...
- html 的实践
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 匪警请拨110——C++
问题描述 匪警请拨110,即使手机欠费也可拨通! 为了保障社会秩序,保护人民群众生命财产安全,警察叔叔需要与罪犯斗智斗勇,因而需要经常性地进行体力训练和智力训练! 某批警察叔叔正在进行智力训练: 1 ...
- 2017中国无人机公开赛 总决赛 CDR Final 竞赛规则
2017中国无人机公开赛总决赛 CDR Final竞赛规则 V2 二〇一七年八月(修订) 一. 竞赛项目描述(一) 无人机绕标竞速赛(专业组)飞行员通过佩戴眼镜或显示屏采用第一视角飞行,使用无线电遥控 ...
- [Java]Java分层概念(转)
service是业务层 action层即作为控制器 DAO (Data Access Object) 数据访问 1.JAVA中Action层, Service层 ,modle层 和 Dao层的功能区分 ...
- centos7下安装配置redis
1.1. Redis下载安装(linux) 1.1.1. 下载: 下载地址:https://redis.io/download 选择合适的版本下载,如下图: 1.1.2. 安装: (1)把下载好的re ...
- python-校验密码小练习
#校验密码是否合法的小练习#1.密码长度5到10位:#2.密码里面必须包含,大写字母,小写字母,数字#3.最多输入5次 写程序过程中遇到了两个问题,第二个循环里的P是把password的值循环传到p里 ...