zoukankan      html  css  js  c++  java
  • C++多线程编程

    多线程是学习SLAM过程中不可缺少的一步,正确的使用多线程能使SLAM系统的运行速度提升很多,达到更高的精度和速度。本节就来学习SLAM中的多线程编程方法。

    线程

    概念

    线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。 一个进程可以有很多线程,每条线程并行执行不同的任务。

    优点

    线程可以提高应用程序在多核环境下处理诸如文件I/O或者socket I/O等会产生堵塞的情况的表现性能。在Unix系统中,一个进程包含很多东西,包括可执行程序以及一大堆的诸如文件描述符地址空间等资源。在很多情况下,完成相关任务的不同代码间需要交换数据。如果采用多进程的方式,那么通信就需要在用户空间和内核空间进行频繁的切换,开销很大。但是如果使用多线程的方式,因为可以使用共享的全局变量,所以线程间的通信(数据交换)变得非常高效。

    C++

    一个简单的Demo

    #include <iostream>
    #include <thread>
    #include <future>
    using namespace std;
    void helloworld()
    {
    cout << "hello world ";
    }
    int main()
    {
    //开启一个线程
    std::thread t(helloworld);
    std::cout << "hello world main thread ";

    //线程的终结
    t.join();

    return 0;
    }

    多线程库

    C++11中终于提供了多线程的标准库,提供了线程管理、保护共享数据、线程间同步操作、原子操作等类。

    多线程库对应的头文件是#include<thread>,类名为std::thread

    一个简单的串行程序如下:

    #include <iostream>
    #include <thread>

    void function_1() {
    std::cout << "I'm function_1()" << std::endl;
    }

    int main() {
    function_1();
    return 0;
    }

    这是一个典型的单线程的单进程程序,任何程序都是一个进程,main()函数就是其中的主线程,单个线程都是顺序执行。

    将上面的程序改造成多线程程序其实很简单,让function_1()函数在另外的线程中执行:

    #include <iostream>
    #include <thread>

    void function_1() {
    std::cout << "I'm function_1()" << std::endl;
    }

    int main() {
    std::thread t1(function_1);
    // do other things
    t1.join();
    return 0;
    }

    分析:

    1. 首先,构建一个std::thread对象t1,构造的时候传递了一个参数,这个参数是一个函数,这个函数就是这个线程的入口函数,函数执行完了,整个线程也就执行完了。
    2. 线程创建成功后,就会立即启动,并没有一个类似start的函数来显式的启动线程。
    3. 一旦线程开始运行, 就需要显式的决定是要等待它完成(join),或者分离它让它自行运行(detach)。注意:只需要在std::thread对象被销毁之前做出这个决定。这个例子中,对象t1是栈上变量,在main函数执行结束后就会被销毁,所以需要在main函数结束之前做决定。
    4. 这个例子中选择了使用t1.join(),主线程会一直阻塞着,直到子线程完成,join()函数的另一个任务是回收该线程中使用的资源。

    线程对象和对象内部管理的线程的生命周期并不一样,如果线程执行的快,可能内部的线程已经结束了,但是线程对象还活着,也有可能线程对象已经被析构了,内部的线程还在运行。

    线程创建

    下面的程序,我们可以用它来创建一个 POSIX 线程:

    #include <pthread.h>
    pthread_create (thread, attr, start_routine, arg)

    在这里,pthread_create 创建一个新的线程,并让它可执行。下面是关于参数的说明:

    参数 描述
    thread 指向线程标识符指针。
    attr 一个不透明的属性对象,可以被用来设置线程属性。您可以指定线程属性对象,也可以使用默认值 NULL。
    start_routine 线程运行函数起始地址,一旦线程被创建就会执行。
    arg 运行函数的参数。它必须通过把引用作为指针强制转换为 void 类型进行传递。如果没有传递参数,则使用 NULL。

    创建线程成功时,函数返回 0,若返回值不为 0 则说明创建线程失败。

    终止线程

    使用下面的程序,我们可以用它来终止一个 POSIX 线程:

    #include <pthread.h>
    pthread_exit (status)

    在这里,pthread_exit 用于显式地退出一个线程。通常情况下,pthread_exit() 函数是在线程完成工作后无需继续存在时被调用。

    如果 main() 是在它所创建的线程之前结束,并通过 pthread_exit() 退出,那么其他线程将继续执行。否则,它们将在 main() 结束时自动被终止。

    打赏
  • 相关阅读:
    基于Visual C++2013拆解世界五百强面试题--题13-找最大公共子字符串
    基于Visual C++2013拆解世界五百强面试题--题12-进制转换
    Color颜色对照表
    根据选择打开相应的程序
    复制一个5G文件只需要两秒,全网最牛方法!
    判断一个男人穷还是富,只看这几点!
    判断一个男人穷还是富,只看这几点!
    判断一个男人穷还是富,只看这几点!
    16年国庆假期期间兼职所悟
    16年国庆假期期间兼职所悟
  • 原文地址:https://www.cnblogs.com/guoben/p/13339266.html
Copyright © 2011-2022 走看看