前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线程本地存储-The Boost C++ Libraries

线程本地存储-The Boost C++ Libraries

作者头像
ccf19881030
发布2020-05-18 17:19:32
1.1K0
发布2020-05-18 17:19:32
举报
文章被收录于专栏:ccf19881030的博客ccf19881030的博客

前言

The Boost C++ Libraries 本博客是Thread Local Storage的一篇译文。关于《The Boost C++ Llibraries》一书的在线完整书的目录,参见The Boost C++ Libraries,Boost库的官网地址是:https://www.boost.org/,翻译这篇博文时Boost库的最新版本是1.73.0

线程本地存储

线程本地存储(TLS)是专用存储区,只能由一个线程访问。 TLS变量可以视为仅对特定线程可见,而对整个程序不可见的全局变量。

示例44.12 使用静态变量同步多个线程

代码语言:javascript
复制
#include <boost/thread.hpp>
#include <iostream>

boost::mutex mutex;

void init()
{
  static bool done = false;
  boost::lock_guard<boost::mutex> lock{mutex};
  if (!done)
  {
    done = true;
    std::cout << "done" << '\n';
  }
}

void thread()
{
  init();
  init();
}

int main()
{
  boost::thread t[3];

  for (int i = 0; i < 3; ++i)
    t[i] = boost::thread{thread};

  for (int i = 0; i < 3; ++i)
    t[i].join();
}

例44.12在三个线程中执行一个函数thread()。 thread()调用另一个函数init()两次,并且init()检查布尔变量done是否为false。 如果是,则将变量设置为true,并将done写入标准输出。

done是所有线程共享的静态变量。 如果第一个线程将done设置为true,则第二个和第三个线程将不会将done写入标准输出。 在任何线程中第二次调用init()都不会将完成写入标准输出。 该示例将打印完成一次。

像done这样的静态变量可用于在进程中进行一次性初始化。 要对每个线程进行一次性初始化,可以使用TLS。

示例44.13 使用TLS同步多个线程

代码语言:javascript
复制
#include <boost/thread.hpp>
#include <iostream>

boost::mutex mutex;

void init()
{
  static boost::thread_specific_ptr<bool> tls;
  if (!tls.get())
  {
    tls.reset(new bool{true});
    boost::lock_guard<boost::mutex> lock{mutex};
    std::cout << "done" << '\n';
  }
}

void thread()
{
  init();
  init();
}

int main()
{
  boost::thread t[3];

  for (int i = 0; i < 3; ++i)
    t[i] = boost::thread{thread};

  for (int i = 0; i < 3; ++i)
    t[i].join();
}

在示例44.13中,静态变量done已替换为TLS变量tls,该变量基于类模板boost::thread_specific_ptr –用bool类型实例化。原则上,tls的工作方式类似于完成:它充当指示是否已完成某些操作的条件。但是,关键的区别在于,由tls存储的值仅对相应线程可见并且可用。

一旦创建了boost::thread_specific_ptr类型的变量,就可以对其进行设置。该变量需要布尔类型的变量的地址,而不是变量本身的地址。使用reset()成员函数,可以将地址存储在tls中。在示例44.13中,动态分配了bool类型的变量,并将其地址(由new返回)存储在tls中。为了避免每次调用init()时都设置tls,成员函数get()用于检查地址是否已经存储。

因为boost :: thread_specific_ptr存储一个地址,所以此类的行为类似于指针。例如,它提供了成员函数operator *和operator->,它们可以像使用指针一样工作。

示例44.13打印了三遍到标准输出。每个线程在第一次调用init()时都会完成打印。因为使用了TLS变量,所以每个线程都使用自己的变量tls。当第一个线程使用指向动态分配的布尔变量的指针初始化tls时,第二个线程和第三个线程中的tls变量仍未初始化。由于TLS变量是每个线程全局的,而不是每个进程全局的,因此在一个线程中使用tls不会更改任何其他线程中的变量。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-05-10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 线程本地存储
    • 示例44.12 使用静态变量同步多个线程
      • 示例44.13 使用TLS同步多个线程
      相关产品与服务
      对象存储
      对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档