还有一个问题没有解决:如何使得初始化工作(比如说构造函数)也是线程安全的。比方说,如果一个引用程序要产生唯一的全局的对象,由于实例化顺序的问题,某个函数会被调用来返回一个静态的对象,它必须保证第一次被调用时就产生这个静态的对象。这里的问题就是如果多个线程同时调用了这个函数,那么这个静态对象的构造函数就会被调用多次,这样错误产生了。解决这个问题的方法就是所谓的“一次实现”(once routine)。“一次实现”在一个应用程序只能执行一次。如果多个线程想同时执行这个操作,那么真正执行的只有一个,而其他线程必须等这个操作结束。为了保证它只被执行一次,这个routine由另一个函数间接的调用,而这个函数传给它一个指针以及一个标志着这个routine是否已经被调用的特殊标志。这个标志是以静态的方式初始化的,这也就保证了它在编译期间就被初始化而不是运行时。因此也就没有多个线程同时将它初始化的问题了。Boost线程库提供了boost::call_once来支持“一次实现”,并且定义了一个标志boost::once_flag及一个初始化这个标志的宏BOOST_ONCE_INIT。List6是一个使用了boost::call_once的例子。其中定义了一个静态的全局整数,初始值为0;还有一个由BOOST_ONCE_INIT初始化的静态boost::once_flag实例。main函数创建了两个线程,它们都想通过传入一个函数调用boost::call_once来初始化这个全局的整数,这个函数是将它加1。main函数等待着两个线程结束,并将最后的结果输出的到std::cout。由最后的结果可以看出这个操作确实只被执行了一次,因为它的值是1。

#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
#include <iostream>int i = 0;
boost::once_flag flag =
BOOST_ONCE_INIT;void init()
{++i;
}void thread()
{boost::call_once(&init, flag);
}int main(int argc, char* argv[])
{boost::thread thrd1(&thread);boost::thread thrd2(&thread);thrd1.join();thrd2.join();std::cout << i << std::endl;return 0;
}
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>// Some sort of connection class that should only be initialized once
struct Conn {static void init( ) {++i_;}static boost::once_flag init_;static int i_;// ...
};int Conn::i_ = 0;
boost::once_flag Conn::init_ = BOOST_ONCE_INIT;void worker( ) {boost::call_once(Conn::init, Conn::init_);// Do the real work...
}Conn c;  // You probably don't want to use a global, so see the// next Recipeint main( ) {boost::thread_group grp;for (int i = 0; i < 100; ++i)grp.create_thread(worker);grp.join_all( );std::cout << c.i_ << '\n';// c.i_ = 1
}

一个共享资源不得不在某个地方被初始化,并且你希望第一次使用这个资源的线程来完成初始化工作。一个once_flag类型和call_once函数能够保证多个线程不会重复的初始化同一个对象。首先,必须使用BOOST_ONCE_INIT宏来初始化这个once_flag对象。boost::once_flag Conn::init_ = BOOST_ONCE_INIT; 之后调用call_once函数,boost::call_once(Conn::init, Conn::init_); 第一个形参是希望被执行一次的初始化函数的地址。

【Boost】boost库中thread多线程详解8——call_once仅运行一次相关推荐

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. 【Boost】boost库中thread多线程详解6——线程组简单例子

    如果你需要创建几个线程,考虑使用一个线程组对象thread_group来组织它们.一个thread_group对象可以使用多种方法管理线程.首先,可以使用一个指向动态创建的线程对象的指针作为参数来调用 ...

  9. 【Boost】boost库中thread多线程详解2——mutex与lock

    1. mutex对象类 mutex类主要有两种:独占式与共享式的互斥量. ▲ 独占式互斥量: mutex: 独占式的互斥量,是最简单最常用的一种互斥量类型 try_mutex: 它是mutex的同义词 ...

最新文章

  1. Google Objective-C Style Guide
  2. 网友抱怨:「苹果除了每年收我的钱,似乎什么都不想做」
  3. [云炬创业基础笔记]第六章商业模式测试10
  4. 行为设计模式 - 中介设计模式
  5. java.io.serializable_java.io.NotSerializableException即使我实现“Serializable”
  6. Lambda表达式实例
  7. GENTLE.NET快速上手
  8. 影视APP直播盒子源码 第三方接口无需采集
  9. 软考-计算机系统知识整理
  10. 【Tensorflow2.0】8、tensorflow2.0_hdf5_savedmodel_pb模型转换[1]
  11. ubuntu加入Windows的AD域(使用SSSD和Realm的方式)
  12. 5G 当自强,根系不能忘
  13. ORACLE ERP consolidation流程(二)
  14. 社交 APP 唔哩星球完成数百万元天使轮融资,投资方为启明创投
  15. Ps制作食物网站展示
  16. macf1-f12按键失灵_枕头2-1-0失灵
  17. 【OpenGL】(step1)开个窗口
  18. unique中译_unique是什么意思_ unique的翻译_音标_读音_用法_例句_爱词霸在线词典...
  19. 阴霾“强势霸屏”长三角 天际上演“失踪的太阳”
  20. Windows 10下载安装openjdk及环境变量配置(以openjdk 8为例)

热门文章

  1. Azkaban编译和安装模式
  2. 字符输入流_Reader类FileReader类介绍
  3. linux内核启动配置,启动linux内核配置
  4. Nginx教程--配置
  5. maven jersey mysql_jersey+maven构建restful服务
  6. 程序片上(内)执行-nandFlash-norFlash
  7. 写入指定长度的字节到文件
  8. 10.10SSD安装盘clover 下开启trim功能
  9. 永乐XIANDAI 08
  10. Service的生命周期