Boost::Thread 多线程的基础知识

简介: Boost.Thread可以使用多线程执行可移植C++代码中的共享数据。它提供了一些类和函数来管理线程本身,还有其它一些为了实现在线程之间同步数据或者提供针对特定单个线程的数据拷贝。头文件:#include 线程定义boost::thread 类是负责启动和管理线程。

Boost.Thread可以使用多线程执行可移植C++代码中的共享数据。它提供了一些类和函数来管理线程本身,还有其它一些为了实现在线程之间同步数据或者提供针对特定单个线程的数据拷贝。
头文件:
#include <boost/thread.hpp>

线程定义
boost::thread 类是负责启动和管理线程。每个boost::thread对象代表一个单独的执行线程,是不可拷贝的。由于它是可以被移动到,所以它们可以被保存到会改变大小的容器中,并且从函数返回。这使得线程创建的详细信息可以被封装到一个函数中。
boost::thread make_thread();

void f()
{
 boost::thread some_thread = make_thread();
 some_thread.join();
}


启动线程
一个新的线程可以通过传递一个可被调用的类型对象来启动,这个对象可以不需要给构造器参数就被唤醒。对象被拷贝到内存,并且在最新创建的线程上唤醒。如果对象不能被拷贝,boost::ref可以以引用的方式来传递给函数对象。在这种情况下,用户的boost.thread必须确保对象的引用的生命期必须比最新创建的执行线程要长。

struct callable
{
    void operator()();
};

boost::thread copies_are_safe()
{
    callable x;
    return boost::thread(x);
} // x is destroyed, but the newly-created thread has a copy, so this is OK

boost::thread oops()
{
    callable x;
    return boost::thread(boost::ref(x));
} // x is destroyed, but the newly-created thread still has a reference
  // this leads to undefined behaviour


如果你用一个函数或者可调用的对象希望创建一个boost::thread 的实例需要提供一些参数,这些可以通过给它的构造体传递另外的参数来办到。

void find_the_question(int the_answer);

boost::thread deep_thought_2(find_the_question,42);
参数被拷贝到内部线程结构里:如果需要传递一个引用,可以使用boost::Ref,只是对可调用对象的引用。
没有指定限制传递的额外参数的数量。

线程中的异常
如果传入到boost::thread构造体的函数或者可调用的对象抛出了一个异常而且唤醒它的不是boosst::thread_interrupted类型,std::terminate()会被调用来结束这个线程。

等待
当代表一个执行线程的线程对象被破坏时,这个线程变成分离的,一旦它被分离,将会继续执行知道唤醒由构造体提供的函数或者可调用对象执行结束,或者程序已经结束。线程也可以通过调用detach()成员函数来显示的分离。在这种情形下,线程对象将不在表示一个当前分离的线程,而是一个非线程体。
为了等待一个线程执行完毕,必须使用join()和timed_join()成员函数。join()会阻塞调用的线程直到线程结束。如果线程刚刚执行结束,或者它已经不代表一个线程,join()会立即返回。timed_join()也是类似的,但是调用它如果在指定的时间流逝后线程仍然没有结束它也会返回。

中断
一个正在运行的线程可以通过调用相应的boost::thread对象的interrupt()成员函数来中断。当被中断的线程在下次执行一个指定的中断点(或者如果它在同时执行一个的时候被锁)并开启中断时,在被中断的线程中就会抛出一个boost::thread_interrupted异常。如果没有被捕获,这会导致结束被中断线程的执行。与其他异常一样,栈就会被释放,自动存储期对象的析构体将会被执行。
如果一个线程需要避免被中断,可以创建一个boost::this_thread::disable_interruption实例。这个类的对象在构造体创建线程的时候禁止了中断,可以在析构体调用之前的任意地方恢复允许中断。
void f()
{
    // interruption enabled here
    {
        boost::this_thread::disable_interruption di;
        // interruption disabled
        {
            boost::this_thread::disable_interruption di2;
            // interruption still disabled
        } // di2 destroyed, interruption state restored
        // interruption still disabled
    } // di destroyed, interruption state restored
    // interruption now enabled
}

通过构造一个boost::this_thread::restore_interruption实例可以临时转换一个boost::this_thread::disable_interruption实例造成的影响,只要在有问题的地方传递一个boost::this_thread::disable_interruption对象。这会重新恢复中断状态到当boost::this_thread_diable_interruption对象被构造时,并且在次禁止中断当boost::this_thread::restore_interruption对象被破坏时。
void g()
{
    // interruption enabled here
    {
        boost::this_thread::disable_interruption di;
        // interruption disabled
        {
            boost::this_thread::restore_interruption ri(di);
            // interruption now enabled
        } // ri destroyed, interruption disable again
    } // di destroyed, interruption state restored
    // interruption now enabled
}
我们可以通过调用boost::this_thread::interruption_enabled()来查询中断的状态。


预定义的中断点
以下函数当允许中断时可能会抛出boost::thread_interrupted异常。
boost::thread::join() 
boost::thread::timed_join() 
boost::condition_variable::wait() 
boost::condition_variable::timed_wait() 
boost::condition_variable_any::wait() 
boost::condition_variable_any::timed_wait() 
boost::thread::sleep() 
boost::this_thread::sleep() 
boost::this_thread::interruption_point()

线程ID
boost::thread::id类可以用来标识一个线程。每个运行的执行线程都有一个特有的ID,可以通过对应的boost::thread的get_id()成员函数来获得ID。

目录
相关文章
|
4月前
|
Java 开发者
Java面试题:请解释内存泄漏的原因,并说明如何使用Thread类和ExecutorService实现多线程编程,请解释CountDownLatch和CyclicBarrier在并发编程中的用途和区别
Java面试题:请解释内存泄漏的原因,并说明如何使用Thread类和ExecutorService实现多线程编程,请解释CountDownLatch和CyclicBarrier在并发编程中的用途和区别
55 0
|
3月前
|
Java 开发者
奇迹时刻!探索 Java 多线程的奇幻之旅:Thread 类和 Runnable 接口的惊人对决
【8月更文挑战第13天】Java的多线程特性能显著提升程序性能与响应性。本文通过示例代码详细解析了两种核心实现方式:Thread类与Runnable接口。Thread类适用于简单场景,直接定义线程行为;Runnable接口则更适合复杂的项目结构,尤其在需要继承其他类时,能保持代码的清晰与模块化。理解两者差异有助于开发者在实际应用中做出合理选择,构建高效稳定的多线程程序。
57 7
|
18天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
14 3
|
18天前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
29 2
|
18天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
27 2
|
18天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
26 1
|
2月前
|
存储 Java 程序员
优化Java多线程应用:是创建Thread对象直接调用start()方法?还是用个变量调用?
这篇文章探讨了Java中两种创建和启动线程的方法,并分析了它们的区别。作者建议直接调用 `Thread` 对象的 `start()` 方法,而非保持强引用,以避免内存泄漏、简化线程生命周期管理,并减少不必要的线程控制。文章详细解释了这种方法在使用 `ThreadLocal` 时的优势,并提供了代码示例。作者洛小豆,文章来源于稀土掘金。
【多线程面试题 二】、 说说Thread类的常用方法
Thread类的常用方法包括构造方法(如Thread()、Thread(Runnable target)等)、静态方法(如currentThread()、sleep(long millis)、yield()等)和实例方法(如getId()、getName()、interrupt()、join()等),用于线程的创建、控制和管理。
|
4月前
|
Java C# Python
线程等待(Thread Sleep)
线程等待(Thread Sleep)
|
3月前
|
SQL 机器学习/深度学习 算法
【python】python指南(一):线程Thread
【python】python指南(一):线程Thread
45 0