Boost多线程编程

 

背景

•       今天互联网应用服务程序普遍使用多线程来提高与多客户链接时的效率;为了达到最大的吞吐量,事务服务器在单独的线程上运行服务程序;

GUI应用程序将那些费时,复杂的处理以线程的形式单独运行,以此来保证用户界面能够及时响应用户的操作。这样使用多线程的例子还有很多。

•       跨平台

创建线程

•       头文件 <boost/thread/thread.hpp>

namespace boost {

class thread;

class thread_group;

}

•       thread():构造一个表示当前执行线程的线程对象

•       explicit thread(const boost::function0<void>& threadfunc)

注:boost::function0<void>可以简单看为:一个无返回(返回void),无参数的函数。这里的函数也可以是类重载operator()构成的函数。

第一种方式:最简单方法

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

•       #include <iostream>

•       void hello()

•       {

•               std::cout <<

•               "Hello world, I''m a thread!"

•               << std::endl;

•       }

•       int main(int argc, char* argv[])

•       {

•               boost::thread thrd(&hello);

•               thrd.join();

•               return 0;

•       }

第二种方式:复杂类型对象作为参数来创建线程

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

•       #include <boost/thread/mutex.hpp>

•       #include <iostream>

•       boost::mutex io_mutex;

•       struct count

•       {

•               count(int id) : id(id) { }

•               void operator()()

•               {

•                       for (int i = 0; i < 10; ++i)

•                       {

•                               boost::mutex::scoped_lock

•                               lock(io_mutex);

•                               std::cout << id << ": "

•                               << i << std::endl;

•                       }

•               }

•               int id;

•       };

•       int main(int argc, char* argv[])

•       {

•               boost::thread thrd1(count(1));

•               boost::thread thrd2(count(2));

•               thrd1.join();

•               thrd2.join();

•               return 0;

•       }

第三种方式:在类内部创建线程

•       (1)类内部静态方法启动线程

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

•       #include <iostream>

•       class HelloWorld

•       {

•       public:

•       static void hello()

•       {

•             std::cout <<

•             "Hello world, I''m a thread!"

•             << std::endl;

•       }

•       static void start()

•       {

•        boost::thread thrd( hello );

•        thrd.join();

•       }

•       };

•       int main(int argc, char* argv[])

•       {

•       HelloWorld::start();

•       return 0;

•       }

•       在这里start()和hello()方法都必须是static方法。

•       (2)如果要求start()和hello()方法不能是静态方法则采用下面的方法创建线程:

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

•       #include <boost/bind.hpp>

•       #include <iostream>

•       class HelloWorld

•       {

•       public:

•       void hello()

•       {

•           std::cout <<

•           "Hello world, I''m a thread!"

•           << std::endl;

•       }

•       void start()

•       {

•        boost::function0< void> f = boost::bind(&HelloWorld::hello,this);

•        boost::thread thrd( f );

•        thrd.join();

•       }

•       };

•       int main(int argc, char* argv[])

•       {

•       HelloWorld hello;

•       hello.start();

•       return 0;

•       }

•       (3)在Singleton模式内部创建线程:

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

•       #include <boost/bind.hpp>

•       #include <iostream>

•       class HelloWorld

•       {

•       public:

•       void hello()

•       {

•           std::cout <<

•           "Hello world, I''m a thread!"

•           << std::endl;

•       }

•       static void start()

•       {

•        boost::thread thrd( boost::bind

•                          (&HelloWorld::hello,&HelloWorld::getInstance() ) ) ;

•        thrd.join();

•       }

•       static HelloWorld& getInstance()

•       {

•        if ( !instance )

•             instance = new HelloWorld;

•        return *instance;

•       }

•       private:

•       HelloWorld(){}

•       static HelloWorld* instance;

•       };

•       HelloWorld* HelloWorld::instance = 0;

•       int main(int argc, char* argv[])

•       {

•       HelloWorld::start();

•       return 0;

•       }

第四种方法:用类内部函数在类外部创建线程

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

•       #include <boost/bind.hpp>

•       #include <string>

•       #include <iostream>

•       class HelloWorld

•       {

•       public:

•       void hello(const std::string& str)

•       {

•               std::cout <<str<< std::endl;

•       }

•       };

•       int main(int argc, char* argv[])

•       {

•       HelloWorld obj;

•       boost::thread thrd( boost::bind(&HelloWorld::hello,&obj,"Hello

•                                      world, I''m a thread!" ) ) ;

•       thrd.join();

•       return 0;

•       }

如果线程需要绑定的函数有参数则需要使用boost::bind。比如想使用 boost::thread创建一个线程来执行函数:void f(int i),

如果这样写:boost::thread thrd(f)是不对的,因为thread构造函数声明接受的是一个没有参数且返回类型为void的型别,而且

不提供参数i的值f也无法运行,这时就可以写:boost::thread thrd(boost::bind(f,1))。涉及到有参函数的绑定问题基本上都

是boost::thread、boost::function、boost::bind结合起来使用。

互斥体

•       一个互斥体一次只允许一个线程访问共享区。当一个线程想要访问共享区时,首先要做的就是锁住(lock)互斥体。

•       Boost线程库支持两大类互斥体,包括简单互斥体(simple mutex)和递归互斥体(recursive mutex)。

有了递归互斥体,单个线程就可以对互斥体多次上锁,当然也必须解锁同样次数来保证其他线程可以对这个互斥体上锁。

•       Boost线程库提供的互斥体类型:

boost::mutex,

boost::try_mutex,

boost::timed_mutex,

boost::recursive_mutex,

boost::recursive_try_mutex,

boost::recursive_timed_mutex,

boost::shared_mutex

•       mutex类采用Scope Lock模式实现互斥体的上锁和解锁。即构造函数对互斥体加锁,析构函数对互斥体解锁。

•       对应现有的几个mutex导入了scoped_lock,scoped_try_lock,scoped_timed_lock.

•       scoped系列的特色就是析构时解锁,默认构造时加锁,这就很好的确定在某个作用域下某线程独占某段代码。

mutex+scoped_lock

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

•       #include <boost/thread/mutex.hpp>

•       #include <boost/bind.hpp>

•       #include <iostream>

•       boost::mutex   io_mutex;

•       void count(int id)

•       {

•              for (int i = 0; i < 10; ++i)

•              {

•                      boost::mutex::scoped_lock    lock(io_mutex);

•                      std::cout << id << ": " << i << std::endl;

•              }

•       }

•       int main(int argc, char* argv[])

•       {

•              boost::thread thrd1(boost::bind(&count, 1));

•              boost::thread thrd2(boost::bind(&count, 2));

•              thrd1.join();

•              thrd2.join();

•              return 0;

•       }

try_mutex+scoped_try_lock

•       void loop(void)

•       {

•              bool running = true;

•              while (running)

•              {

•                      static boost::try_mutex iomutex;

•                      {

•                              boost::try_mutex::scoped_try_lock    lock(iomutex);//锁定mutex

•                              if (lock.owns_lock())

•                              {

•                                     std::cout << "Get lock." << std::endl;

•                              }

•                              else

•                              {

•                                     // To do

•                                     std::cout << "Not get lock." << std::endl;

•                                     boost::thread::yield(); //释放控制权

•                                     continue;

•                              }

•                      } //lock析构,iomutex解锁

•              }

•       }

timed_mutex+scoped_timed_mutex

•       void loop(void)

•       {

•              bool running = true;

•              while (running)

•              {

•                      typedef boost::timed_mutex MUTEX;

•                      typedef MUTEX::scoped_timed_lock LOCK;

•                      static MUTEX iomutex;

•                      {

•                              boost::xtime xt;

•                              boost::xtime_get(&xt,boost::TIME_UTC);

•                              xt.sec += 1; //超时时间秒

•                              LOCK lock(iomutex, xt); //锁定mutex

•                              if (lock.owns_lock())

•                              {

•                                     std::cout << "Get lock." << std::endl;

•                              }

•                              else

•                              {

•                                     std::cout << "Not get lock." << std::endl;

•                                     boost::thread::yield(); //释放控制权

•                              }

•                              //::sleep(10000); //长时间

•                      } //lock析构,iomutex解锁

•                      //::sleep(250);

•              }

•       }

shared_mutex

•       应用boost::thread的shared_mutex实现singled_write/multi_read的简单例子

•       #include <iostream>

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

•       #include <boost/thread/shared_mutex.hpp>

•       using namespace std;

•       using namespace boost;

•       boost::shared_mutex shr_mutex;

•       /// 这个是辅助类,能够保证log_info被完整的输出

•       class safe_log {

•       public:

•           static void log(const std::string& log_info) {

•               boost::mutex::scoped_lock lock(log_mutex);

•               cout << log_info << endl;

•           }

•       private:

•           static boost::mutex log_mutex;

•       };

•       boost::mutex safe_log::log_mutex;

•       void write_process() {

•           shr_mutex.lock();

•           safe_log::log("begin of write_process");

•           safe_log::log("end of write_process");

•           shr_mutex.unlock();

•       }

•       void read_process() {

•           shr_mutex.lock_shared();

•           safe_log::log("begin of read_process");

•           safe_log::log("end of read_process");

•           shr_mutex.unlock_shared();

•       }

•       int main() {

•           thread_group threads;

•           for (int i = 0; i < 10; ++ i) {

•               threads.create_thread(&write_process);

•               threads.create_thread(&read_process);

•           }

•           threads.join_all();

•           ::system("PAUSE");

•           return 0;

•       }

条件变量

•       有的时候仅仅依靠锁住共享资源来使用它是不够的。有时候共享资源只有某些状态的时候才能够使用。

比方说,某个线程如果要从堆栈中读取数据,那么如果栈中没有数据就必须等待数据被压栈。这种情

况下的同步使用互斥体是不够的。另一种同步的方式--条件变量,就可以使用在这种情况下。

•       boost::condition

typedef condition_variable_any condition;

void wait(unique_lock<mutex>& m);

•       boost::condition_variable

template<typename lock_type>

void wait(lock_type& m);

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

•       #include <boost/thread/mutex.hpp>

•       #include <boost/thread/condition.hpp>

•       #include <iostream>

•       const int BUF_SIZE = 10;

•       const int ITERS = 100;

•       boost::mutex io_mutex;

•       class buffer

•       {

•       public:

•              typedef boost::mutex::scoped_lock scoped_lock;

•              buffer()

•              : p(0), c(0), full(0)

•              {

•              }

•              void put(int m)

•              {

•                      scoped_lock lock(mutex);

•                      if (full == BUF_SIZE)

•                      {

•                              {

•                                     boost::mutex::scoped_lock lock(io_mutex);

•                                     std::cout << "Buffer is full. Waiting..." << std::endl;

•                              }

•                              while (full == BUF_SIZE)

•                                     cond.wait(lock);

•                      }

•                      buf[p] = m;

•                      p = (p+1) % BUF_SIZE;

•                      ++full;

•                      cond.notify_one();

•              }

•              int get()

•              {

•                      scoped_lock lk(mutex);

•                      if (full == 0)

•                      {

•                              {

•                                     boost::mutex::scoped_lock lock(io_mutex);

•                                     std::cout << "Buffer is empty. Waiting..." << std::endl;

•                              }

•                              while (full == 0)

•                                     cond.wait(lk);

•                      }

•                      int i = buf[c];

•                      c = (c+1) % BUF_SIZE;

•                      --full;

•                      cond.notify_one();

•                      return i;

•              }

•       private:

•                      boost::mutex mutex;

•                      boost::condition cond;

•                      unsigned int p, c, full;

•                      int buf[BUF_SIZE];

•       };

•       buffer buf;

•       void writer()

•       {

•              for (int n = 0; n < ITERS; ++n)

•              {

•                      {

•                              boost::mutex::scoped_lock lock(io_mutex);

•                              std::cout << "sending: " << n << std::endl;

•                      }

•                      buf.put(n);

•              }

•       }

•       void reader()

•       {

•              for (int x = 0; x < ITERS; ++x)

•               {

•                      int n = buf.get();

•                      {

•                              boost::mutex::scoped_lock lock(io_mutex);

•                              std::cout << "received: " << n << std::endl;

•                      }

•              }

•       }

•       int main(int argc, char* argv[])

•       {

•              boost::thread thrd1(&reader);

•              boost::thread thrd2(&writer);

•              thrd1.join();

•              thrd2.join();

•              return 0;

•       }

线程局部存储

•       函数的不可重入。

•       Boost线程库提供了智能指针boost::thread_specific_ptr来访问本地存储线程(thread local storage)。

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

•       #include <boost/thread/mutex.hpp>

•       #include <boost/thread/tss.hpp>

•       #include <iostream>

•       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(int argc, char* argv[])

•       {

•              boost::thread thrd1(count(1));

•              boost::thread thrd2(count(2));

•              thrd1.join();

•              thrd2.join();

•              return 0;

•       }

仅运行一次的例程

•       如何使得初始化工作(比如说构造函数)也是线程安全的。

•       “一次实现”(once routine)。“一次实现”在一个应用程序只能执行一次。

•       Boost线程库提供了boost::call_once来支持“一次实现”,并且定义了一个标志boost::once_flag及一个初始化这个标志的宏 BOOST_ONCE_INIT。

•       #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;

•       }

Boost线程库的未来

•       Boost线程库正在计划加入一些新特性。其中包括boost::read_write_mutex,它可以让多个线程同时从共享区中读取数据,

但是一次只可能有一个线程向共享区写入数据;boost::thread_barrier,它使得一组线程处于等待状态,知道所有得线程

都都进入了屏障区;boost::thread_pool,他允许执行一些小的routine而不必每一都要创建或是销毁一个线程。

•       Boost线程库已经作为标准中的类库技术报告中的附件提交给C++标准委员会,它的出现也为下一版C++标准吹响了第一声号角。

委员会成员对 Boost线程库的初稿给予了很高的评价,当然他们还会考虑其他的多线程库。他们对在C++标准中加入对多线程的

支持非常感兴趣。从这一点上也可以看出,多线程在C++中的前途一片光明。

Boost多线程编程的更多相关文章

  1. boost多线程使用简例

    原文链接:http://www.cppblog.com/toMyself/archive/2010/09/22/127347.html C++ Boost Thread 编程指南 转自cnblog: ...

  2. [转]Linux 的多线程编程的高效开发经验

    Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多线程 API 有一些细微和隐晦的差别.不注意这些 Linux 上的一些开发陷阱,常常会导致程序问题不穷,死锁不断.本文中我们 ...

  3. [转载] C++ 多线程编程总结

    原文: http://www.cnblogs.com/zhiranok/archive/2012/05/13/cpp_multi_thread.html 在开发C++程序时,一般在吞吐量.并发.实时性 ...

  4. Linux 的多线程编程的高效开发经验(转)

    http://www.ibm.com/developerworks/cn/linux/l-cn-mthreadps/ 背景 Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多 ...

  5. Linux 的多线程编程的高效开发经验

    http://www.ibm.com/developerworks/cn/linux/l-cn-mthreadps/ 背景 Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多 ...

  6. boost多线程入门介绍

    :first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-previ ...

  7. Boost多线程

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

  8. 转 c++多线程编程

    c++多线程编程 一直对多线程编程这一块很陌生,决定花一点时间整理一下. os:ubuntu 10.04  c++ 1.最基础,进程同时创建5个线程,各自调用同一个函数 #include <io ...

  9. 让Duilib多线程编程更easy

    一.Duilib不能开发多线程程序? 记得非常久曾经就听有人说过Duilib的多线程支持性不好,原因是Duilib里面的控件是用数组管理的全局变量,不能进行多线程訪问,加锁非常麻烦.事实上这个说法是非 ...

随机推荐

  1. go build 和 go run区别

  2. MyBatis-Plugins 的创建流程与执行顺序

    一.插件的解析,所有插件都会被添加到 InterceptorChain 类中,用于后续处理 org.apache.ibatis.builder.xml.XMLConfigBuilder private ...

  3. 设计模式---领域规则模式之解析器模式(Interpreter)

    前提:领域规则模式 在特定领域内,某些变化虽然频繁,但可以抽象为某种规则.这时候,结合特定领域,将问题抽象为语法规则,从而给出该领域下的一般性解决方案. 典型模式 解析器模式:Interpreter ...

  4. java中long类型的比较

    int类型最大存储10位,因此很多地方要用到long类型,它的存储位数是+-19位 范围:-9223372036854775808到9223372036854775807解释:long类型是64位的也 ...

  5. Chrome Dev Tools: Code Folding in CSS and Javascript for improved code readiability

    Note : Apply for google chrome canary. You can fold code blocks in CSS (and Sass) and javascript fil ...

  6. docker 系列 - 容器数据持久化和数据共享

    docker 主要有两种数据存储形式, 一种是storage driver(也叫做 Graph driver), 另一种是 volume driver. stroage driver主要是存储那些无状 ...

  7. SQL Server进阶(十二)常用函数

    在SQL 2012基础教程中列出子句是按照以下顺序进行逻辑处理. FROM WHERE GROUP BY HAVING SELECT ORDER BY FROM TableName WHERE Use ...

  8. 29. SpringBoot Redis 非注解

    1. 引入依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spr ...

  9. bash test命令探秘

    shell 测试条件命令 http://blog.csdn.net/yangruibao/article/details/7427503 test 和 [ 命令 虽然 Linux 和 UNIX 的每个 ...

  10. vivalidi 一款由Web技术诞生的Web浏览器

    vivalidi https://vivaldi.com/ A million ways to customize everything The world is a colorful place b ...