如何在linux上使用boost:thread-C/C++

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在linux上使用boost:thread-C/C++相关的知识,希望对你有一定的参考价值。

    首先需要安装boost,步骤如下:

  下载到 boost_1_49_0.tar.bz2 (当然,其他压缩格式也可以)后,可以把它放在用户目录下,即:~/

  解压缩:tar -jxvf boost_1_49_0.tar.bz2

  这样,出现文件夹:~/boost_1_49_0

  然后进入:$ cd boost_1_49_0

  你会发现有一个sh命令:bootstrap.sh

  运行它:$ ./bootstrap.sh     (boost自己的get start文档中说设置参数 --prefix=dir 其中dir为你想指定的安装文件夹,我建议就不用加这个参数,它会默认安装到/usr/local)

  结束后出现一个可执行文件: ~/boost_1_49_0/b2

  运行这个文件: $ sudo ./b2 install   (Ubuntu用户千万别忘了加sudo,不然安装后将无法完全使用)

  编译安装时间比较长,根据不同机器的情况20~40分钟。结束后即安装完毕。


    boost::thread的使用

#include <boost/thread.hpp>
#include <iostream>

void task1()  
    // do stuff
    std::cout << "This is task1!" << std::endl;


void task2()  
    // do stuff
    std::cout << "This is task2!" << std::endl;


int main (int argc, char ** argv) 
    using namespace boost; 
    thread thread_1 = thread(task1);
    thread thread_2 = thread(task2);

    // do other stuff
    thread_2.join();
    thread_1.join();
    return 0;

  编译时的命令为:
$ g++ -I./inlcude -L./lib example.cpp -lboost_thread -o example
编译之后会出现一个 example 的可执行文件,可以运行:./example , 结果显示:
This is task2!
This is task1!

  可能你在运行时会出现这样的错误:error while loading shared libraries: libboost_thread.so.1.49.0: cannot open shared object file: No such file or directory

  这是因为要用到的库不在默认的环境变量里,可以使用下面的命令添加:
$ sudo ldconfig /usr/local/lib

  添加后,再执行./example,这样你就完成了你的第一个boost::thread程序。

参考技术A   使用boost thread的库函数构建多线程的c++程序,了解了基本的thread创建,线程同步以及线程本地存储的使用。都在一个代码实例中进行了 验证。其中还有一个条件变量的使用在不好在一个代码中实现,以后有时间在编写验证一下。
  源代码
  /*************************************************************************
  > File Name: thread_demo.cpp
  > Author: Liu Xin
  > Mail: liu_x_0625@126.com
  > Created Time: 2012年10月14日 星期日 10时54分46秒
  ************************************************************************/

  #include<iostream>
  #include<sstream>
  #include<boost/thread/thread.hpp>
  #include<boost/thread/mutex.hpp>
  #include<boost/bind.hpp>
  #include<boost/thread/tss.hpp>

  using namespace std;

  const int MAX_THREAD_NUM=5;

  int gCount=0;
  boost::mutex mutex;
  boost::mutex io_mutex;
  boost::thread_specific_ptr<string> ptr; // 线程本地存储访问

  void hello(int iThreadId)
  
  // 这两个cout语句在多线程的时候还是汇出现io争用的情况,出现打印混乱, 所以要加锁
  
  boost::mutex::scoped_lock lock(io_mutex);
  std::cout << "thread " << iThreadId << ": " <<
  "hello world boost thread."
  << std::endl;
  std::cout << "thread " << iThreadId << ": " <<
  "oh~, I am a little tired, give me 10 seconds, sleeping zzzzz..."
  << std::endl;
  

  ptr.reset(new string("hello"));

  for(int i=0; i<10; i++)
  
  
  boost::mutex::scoped_lock lock(mutex);

  stringstream ss;
  ss << iThreadId;
  (*ptr) = "thread id: " + ss.str();
  std::cout << (*ptr) << std::endl;

  std::cout << "global count: " << ++gCount << std::endl;

  
  sleep(1);
  
  

  int main()
  
  boost::thread* ths[MAX_THREAD_NUM]=NULL;
  for (int i=0; i<MAX_THREAD_NUM; i++)
  
  ths[i] = new boost::thread(boost::bind(&hello, i+1));
  

  for (int i=0; i<MAX_THREAD_NUM; i++)
  ths[i]->join();

  std::cout << "thread all finished." << std::endl;
  return 0;
  

  说明
  1、代码实现了一个线程函数,main函数中创建多个线程对象调用该线程函数,并等待每个线程结束
  2、线程函数中先输出两行文字,因为io输出是争用资源,需要加锁,否则会出现打印混乱
  3、在for循环中,对共享资源gCount进行++操作,同时输出到标准输出中,也许要进行互斥体加锁
  4、加锁mutex根据RAII实现,也就是scope_lock,退出则自动解锁,因此,此处sleep放在外面 是为了验证多线程执行++gCount操作是真正的多线程。如果放在里面的话,由于lock还未释放,其他线程会一直等到本线程的for循环执行完成才获得锁,实际上变成了伪多线程了,无意义
  5、boost::thread_specific_ptr是线程本地存储的访问 指针,用于验证线程本地存储的效果

在 Linux 上是不是将 boost 内存映射文件归零

【中文标题】在 Linux 上是不是将 boost 内存映射文件归零【英文标题】:Is boost memory mapped file zeroed on Linux在 Linux 上是否将 boost 内存映射文件归零 【发布时间】:2014-02-25 20:51:46 【问题描述】:

我正在重新学习 C++,我需要使用内存映射文件。我决定使用 boost(因为它似乎是可靠的库)。

我创建了一个映射到双精度数组的内存映射文件,并写入该数组中的第一个双精度。磁盘文件在前四个字节中包含一些数据,其余的都归零,这对我来说很奇怪,因为通常如果我在 C++ 中获得指向内存位置的指针,在大多数情况下我必须假设它包含垃圾。

我是否可以保证新创建的内存映射文件将被清零(至少在 Linux 上)?我没有找到任何参考。

BOOST_AUTO_TEST_CASE(OpenMMapFile)

boost::iostreams::mapped_file file;

boost::iostreams::mapped_file_params params;

params.path = "/tmp/mmaptest-1";
params.mode = std::ios::in | std::ios::out;
params.new_file_size =  10*sizeof(double);

file.open(params);

double* data = static_cast<double*>((void*)file.data());

data[0] = 12;

file.close();


这是文件内容:

cat /tmp/mmaptest-1 | base64
AAAAAAAAKEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=

编辑

正如@Zan 所指出的 --- boost 实际上使用 ftruncate 来调整 mmaped 文件的大小,因此可以保证归零(至少在 Linux 上)。

【问题讨论】:

在 Unix/Linux 上,操作系统提供了数据不泄露的安全保证,因此当分配文件或内存区域时,它不能允许进程查看磁盘/内存上的内容在以前的文件/进程中。满足此保证的最简单方法是将内存归零。这就是它的作用。 richard 将 linux 与 Windows95 进行比较? 【参考方案1】:

内存映射文件包含文件中的任何内容。

如果它是一个新文件,它已被扩展为正确的大小,并且扩展名将包含零。扩展文件通常使用 ftruncate 函数完成。

ftruncate 联机帮助页说:

   If  the  file  previously  was larger than this size, the extra data is
   lost.  If the file previously was shorter,  it  is  extended,  and  the
   extended part reads as null bytes ('\0').

所以是的,零是保证的。

【讨论】:

【参考方案2】:

我认为 boost 正在为您将文件归零,以实现映射地址空间真正由磁盘空间而不是稀疏文件备份。 这很慢,特别是如果您想预先创建一个大地址空间, 它可能永远不会被完全使用——只是为了让你可以在这个地址空间中分配许多对象。 他们正在这样做,因为在 UNIX 上没有可用的方法来处理写入内存映射稀疏文件时的磁盘空间不足(暂时忽略 setjmp/longjmp 之类的病态解决方案)。 但是您仍然有可能其他一些进程会截断磁盘上的文件, 在这种情况下,前面提到的问题再次出现。

不幸的是,在存在结构化异常处理的 Windows 上,他们也在这样做(分配与地址空间大小匹配的磁盘空间,而不是使用稀疏文件)。

【讨论】:

这是不真实的,因为正如在这个问题中建立的那样:***.com/q/26682229/7918,实际上磁盘空间没有预先分配! 上次尝试时,对 boost 库的匹配调用挂了很长时间。这可能同时发生了变化,但我对此表示怀疑,因为提到的问题仍然存在。 我刚试过这个,调用 boost 来创建一个托管内存映射文件并在其中分配一个大对象,立即返回。这意味着,在文件创建期间或分配对象时不会分配磁盘空间。这意味着,一个人冒着 SIGSEGV 的风险。请参阅 mmap 的手册页。

以上是关于如何在linux上使用boost:thread-C/C++的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 g++ 在 Linux 上使用 boost/shared_ptr.hpp 编译 c++ 程序

在 Linux 上是不是将 boost 内存映射文件归零

如何在c ++代码块窗口中使用boost 1.63库?

如何在 pkg-config 中使用 C++ Boost 库?

在 Linux 中使用 fork() + execlp 和 boost::asio 时解决重用错误

Linux C++ 将 Boost 编译到我的程序中