• c++11の简单线程管理


    1、简单的例子

    #include "stdafx.h"
    #include <iostream>
    #include <thread>
    
    
    
    void function_1() 
    {
        for (size_t i = 0; i < 100; i++)
        {
            std::cout << "from function 1" << std::endl;
        }    
    }
    
    int main()
    {
        std::thread t(function_1);
    
        for (size_t i = 0; i < 100; i++)
        {
            std::cout << "from function main"<<std::endl;
        }
    
        t.join();
    
        std::getchar();
    
        return 0;
    }

    在一个线程中,开了另一个线程去干另一件事,使用join函数后,原始线程会等待新线程执行结束之后,再去销毁线程对象。
    这样有什么好处?---->因为它要等到新线程执行完,再销毁,线程对象,这样如果新线程使用了共享变量,等到新线程执行完再销毁这个线程对象,不会产生异常。如果不使用join,使用detch,那么新线程就会与原线程分离,如果原线程先执行完毕,销毁线程对象及局部变量,并且新线程有共享变量或引用之类,这样新线程可能使用的变量,就变成未定义,产生异常或不可预测的错误。
    所以,当你确定程序没有使用共享变量或引用之类的话,可以使用detch函数,分离线程。
    但是使用join可能会造成性能损失,因为原始线程要等待新线程的完成,所以有些情况(前提是你知道这种情况,如上)使用detch会更好。

    上述代码如果主函数中的for循环发生异常,t.join就不会执行,因此需要注意线程安全

    2、线程安全

        std::thread t(function_1);
        try
        {
            for (size_t i = 0; i < 100; i++)
            {
                std::cout << "from function main" << std::endl;
            }
            
        }
        catch (const std::exception&)
        {
            t.join();
        }
        t.join();
    View Code

    3、线程可执行的类型

    在上述例子中,我们t()的参数是一个function,c++中规定,其可以是一个可调用对象即可(可被调用的对象构造),可以是函数,构造函数,lmbd表达式等,当然也可以加参数

     class Func {
     public:
        void operator()(std::string s)   //重载了运算符 ()
        {
            std::cout << s << std::endl;
        }
     };
    
    int main()
    {
        std::string s= "i love u";
        std::thread t((Func()),s);
        try
        {
            for (size_t i = 0; i < 100; i++)
            {
                std::cout << "from function main" << std::endl;
            }
            
        }
        catch (const std::exception&)
        {
            t.join();
            throw;
        }
        t.join();
    
        std::getchar();
    
        return 0;
    }
    View Code

    4、线程通讯

    如果需要减少复制操作,我们可以使用引用类型

    void operator()(std::string & s) //重载了运算符 ()
    {
    std::cout << s << std::endl;
    }

    但是对于线程间的通讯,是无效的

    我们可以在调用的时候

    std::thread t((Func()),std::ref( s));

    此中方法我们可以实现引用的线程间传递,但是也造成了不安全,我们可以使用std::move();

    c++11中有很多对象只能够被移动,不能都被传递复制,例如(thread)

    5、获取cpu支持同时工作的线程数std::cout<< std::thread::hardware_concurrency()<<std::endl;

     多线程一----多线程的应用

     多线程二----简单线程管理

    多线程三----数据竞争和互斥对象

    多线程四----死锁和防止死锁

    多线程五----unick_lock和once_flag

    多线程六----条件变量

    多线程七----线程间通信

  • 相关阅读:
    cnetos7设置中文显示及中文输入法
    大数据、云计算和人工智能
    木马可以做什么
    百度搜索语法
    python知识点
    反向代理&集线器和交换机的区别&广播地址&seq与ack的区别
    转台轴承-YRT转台轴承-机床转台轴承选型浅析
    光栅尺与PLC的配合使用
    STM32 keil printf的使用
    keil编写程序完成后debug前面出现绿色框框
  • 原文地址:https://www.cnblogs.com/xietianjiao/p/10449139.html
Copyright © 2020-2023  润新知