zoukankan      html  css  js  c++  java
  • STL线程库简介

    STL线程库的前身是boost::thread,在C++ 11标准化后便正式归纳入了stl库,通过它我们可以很容易实现跨平台的线程管理。

    线程管理

    在std::thread库中,一个线程用的是一个thread对象表示,当创建一个thread对象时即创建一个线程,一个简单的示例如下:

        #include <iostream>
        #include <thread>
        using namespace std;

        void thread_entry(const char* arg)
        {
            cout << "thread "<<
    this_thread::get_id() << " created: " << arg << endl;
        }

        int main()
        {
            thread
    thrd(thread_entry, "hello world");
            
    thrd.join();
            return 0;
        }

    这里我通过thread对象创建了一个线程,并调用join函数等待线程结束。thead对象的构造函数中是可以传入参数的,非常方便。

    std::this_thread名字空间

    在前面的例子中,还用到了一个this_thread::get_id()函数用以获取当前线程的tid,std::this_thread名字空间提供了如下函数以管理当前线程:

    • yield
    • get_id
    • sleep_for
    • sleep_until

    基本上从名字里就可以猜出它们的功能了。以其中的sleep_for函数为例,它提供了一个跨平台的sleep功能,再也不用自己封装了:

        std::chrono::milliseconds dura(2000);
        std::this_thread::sleep_for(dura);

    PS:在gcc中使用这个函数时,需要再编译的时候加-D_GLIBCXX_USE_NANOSLEEP选项,否则报语法错误,具体原因可以参看这篇文章

    Linux平台的运行错误

    上述代码在Windows平台运行良好,但在Linux上运行的时候发现如下错误:

        tianfang > run
        terminate called after throwing an instance of 'std::system_error'
            what(): Operation not permitted
        Aborted
        tianfang >

    然后在StackOverFlow上找到了答案:在链接的时候要加 –pthread 选项。这个应该算个bug了。

    删除Thread对象

    我最初以为当thread对象删除时会自动杀掉线程,运行时却发现:thread对象删除时,如果没有调用join或attach,就会报异常。为了演示这一过程,首先我们把main函数改成如下所示:

        int main()
        {
            thread thrd(thread_entry, "hello world");
            //thrd.join();
            return 0;
        }

    运行该代码时,就会发现如下错误:

        tianfang > run
        terminate called without an active exception
        Aborted
        tianfang >

    也就是说,thread对象并不会自动管理线程结束,需要手动控制。常见的控制手段有两个,join和detach。join已经介绍过,用于等待线程结束,而detach的功能是托管线程,线程仍然继续运行至结束,但不再受到thread对象控制。

    对线程编程模型比较熟悉的人可能会发现:它并没有提供一个强制终止线程的选项。在boost的this_thread名字空间下其实是提供了终止线程的函数的,但是并没有纳入stl中,可见标准委员会也是不建议强制终止这种不健壮的做法。

    互斥和同步

    互斥体

    stl中对mutex划分得很细,按是否递归、是否超时分为四个对象:

    • mutex
    • timed_mutex
    • recursive_mutex
    • recursive_timed_mutex

    这四个对象的操作函数大体上都是如下几个:

    • lock    获取锁
    • trylock    尝试获取锁
    • unlock    释放锁
    • try_lock_for    在一定时间范围内尝试获取锁(有超时功能的mutex才能用)
    • try_lock_until    尝试获取锁到某个时间点位置(有超时功能的mutex才能用)

    除了直接使用这几个类外,也可以使用lock_guar、unique_lock之类的的封装类,它的功能上类似C#的lock关键字(lock范围并不等价),在指定范围内自动获取锁,出了该范围外自动解锁,可有效防止加解锁不对称。

    另外,stl也提供了try_lock和lock的泛型方法实现批量获取锁定,这里就不多介绍了。

    条件变量

    stl中对条件变量封装的是condition_variable类,它的基本使用方式和系统api差不多,如下是一个生产者/消费者的例子:

        #include <condition_variable>
        #include <mutex>
        #include <thread>
        #include <iostream>
        #include <queue>
        #include <chrono>
        using namespace std;

        int main()
        {
            queue<int> buffer;
            mutex m;
            condition_variable cond_var;
            int num = 0;

            thread producer([&]()
            {
                while (true)
                {
                    this_thread::sleep_for(chrono::seconds(1));

                    unique_lock<std::mutex> lock(m);

                    num++;
                    std::cout << "producing " << num << '\n';
                    buffer.push(num);

                    cond_var.notify_one();
                }
            });

            thread consumer([&]()
            {
                while (true)
                {
                    unique_lock<std::mutex> lock(m);

                    if(buffer.empty())
                        cond_var.wait(lock);

                    std::cout << "consuming " << buffer.front() << '\n';
                    buffer.pop();
                }
            });

            producer.join();
            consumer.join();
        }

    条件变量还有其它几个封装,这里就不多介绍了。

    其它

    其它几个同步互斥的类,如栅栏、读写锁等并没有纳入STL,如果要使用它们,可以直接使用boost库。

  • 相关阅读:
    OPPO R9sPlus MIFlash线刷TWRP Recovery ROOT详细教程
    OPPO R11 R11plus系列 解锁BootLoader ROOT Xposed 你的手机你做主
    努比亚(nubia) M2青春版 NX573J 解锁BootLoader 并进入临时recovery ROOT
    华为 荣耀 等手机解锁BootLoader
    青橙 M4 解锁BootLoader 并刷入recovery ROOT
    程序员修炼之道阅读笔03
    冲刺8
    典型用户模板分析
    学习进度八
    冲刺7
  • 原文地址:https://www.cnblogs.com/TianFang/p/2878519.html
Copyright © 2011-2022 走看看