c++多线程中常用的使用方法

1)promise(保证)和future的联合使用,实现两个线程的数据传递

#include <iostream>
#include<thread>
#include<future>

using namespace std;

//promise用法:可以给线程一个值,而从另一个线程读出该值
// 实现了两个线程的数据传递!
void myPromise(std::promise<int>& tmp,int num)//promise线程
{
    
    
        //在这里假使处理复杂的计算,最后得出一个值,并返回
        num = num + 20;
        tmp.set_value(num);
}

//另一个线程可以得到promise计算后得到的值
void myFuture(std::future<int>& tmp)
{
    
    
        cout<<"myFuture thread receive value is : "<< tmp.get()<<endl;
}

int main()
{
    
    
        std::promise<int> pro;
        std::thread th1(myPromise,std::ref(pro),10); //创建promise线程时,第二个参数一定要用引用
        th1.join();

        std::future<int> result = pro.get_future();
        std::thread th2(myFuture,std::ref(result));  //std::ref( pro.get_future())用临时对象不可以;
        th2.join();
        
        return 0;
}

//输出结果:myFuture thread receive value is : 30
2) package_task的使用,把任务从新包装起来,案例代码如下:

#include <iostream>
#include<thread>
#include<future>

using namespace std;

int func(void)
{
    
    
        cout<<"start----- thread_id is : "<<std::this_thread::get_id()<<endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(2000));
        cout<<"end-------- thread_id is : "<<std::this_thread::get_id()<<endl;
        return 5;
}

//package_task类模板,可以包装任何可调用对象
int main()
{
    
    
        std::packaged_task<int()> task(func);
        std::thread th(std::ref(task)); //package_task里面有一个成员函数get_future(),可以返回一个future对象;
        th.join();
       std::future<int> result = task.get_future();
       cout<<result.get()<<endl;
        return 0;
}

3)//std::async和std::future一起配合使用

#include <iostream>
#include<thread>
#include<mutex>
#include<list>
#include<future>

// std::async和std::future的用法:
// async是一个函数模板,启动一个线程;std::future是类模板,当async启动任务后,会返回std::future对象;
// std::future对象里面有需要的返回值;
using namespace std;

int func(void)
{
    
    
        cout<<"start----- thread_id is : "<<std::this_thread::get_id()<<endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(2000));
        cout<<"end-------- thread_id is : "<<std::this_thread::get_id()<<endl;
        return 5;
}

//std::launch::deferred参数时,等待wait或者get返回,如果没有这两个函数,直接运行接下来代码
//std::launch::deferred参数不会创建新线程!!!
//std::future两个成员函数,get是等待线程处理完返回结果;wait是等待线程处理完,不返回结果
int main()
{
    
    
        cout<<"main thread start----- thread_id is : "<<std::this_thread::get_id()<<endl;
        std::future<int> result = std::async(func); //程序不会卡到这里!!!这里存在一个绑定关系
        cout<<"********main run*********"<<endl;
        cout<<result.get()<<endl; //程序会卡到这里,等待线程返回结果(利用的是std::future的成员函数get)
        return 0;
}

4)//条件变量与互斥量的配合使用方法:

#include <iostream>
#include<thread>
#include<mutex>
#include<list>
#include<condition_variable>
//条件变量是和互斥量配合使用!

using namespace std;

 class A
 {
    
    
public:
        void inQueue(void)
        {
    
    
                for(int i = 0; i<10000;i++)
                {
    
    
                        cout<<"insert message : "<<i<<endl;
                        {
    
    
                                std::unique_lock<std::mutex> uniqueLock(mtx); 
                                message.push_back(i);
                                cond.notify_one();
                        }
                }
        }
        void outQueue(void)
        {
    
    
                for(int i = 0 ; i<10000; i++)
                {
    
    
                        std::unique_lock<std::mutex> uniqueLock(mtx); //自动加锁
			//wait跟互斥量的关系:wait阻塞解锁,wait唤醒加锁!!!
                        cond.wait(uniqueLock,[this](){
    
     //如果参数2是false,解锁等待;如果是true,加锁完成后,继续执行下面代码
                                if(!message.empty()) 
                                        return true;
                                else
                                        return false; //可以处理虚假唤醒,就是说容器没有数据,但被唤醒了,执行解锁等待。
                        });       
                        int cmd = message.front();
                        message.pop_front();             
                        cout<<"out cmd---------- is :"<<cmd<<endl;     
                }//出作用域,uniqueLock锁释放;
        }
private:
        std::list<int> message;
        std::condition_variable cond;
        std::mutex mtx;
 };

int main()
{
    
    
        A a;
        std::thread th1(&A::inQueue,&a);
        std::thread th2(&A::outQueue,&a);
        th1.join();
        th2.join();
        return 0;
}

5)互斥量的使用方法:

#include <iostream>
#include<thread>
#include<mutex>
#include<list>
#include<condition_variable>

using namespace std;

 class A
 {
    
    
public:
        void inQueue(void)
        {
    
    
                for(int i = 0; i<10000;i++)
                {
    
    
                        cout<<"insert message : "<<i<<endl;
                        {
    
    
                                std::unique_lock<std::mutex> uniqueLock(mtx); 
                                message.push_back(i);
                        }
                       std::this_thread::sleep_for(std::chrono::milliseconds(1));
                }
        }
        void outQueue(void)
        {
    
    
                for(int i = 0; i<10000;i++)
                {
    
    
                        if(!message.empty())
                        {
    
    
                                 int cmd = 0;
                                 {
    
    
                                        std::unique_lock<std::mutex> uniqueLock(mtx); 
                                        cmd = message.front();
                                        message.pop_front();
                                 }
                                cout<<"out cmd is :"<<cmd<<endl;
                        }
                        else
                        {
    
    
                                cout<<"empty---------------i: "<<i<<endl;
                        }
                       std::this_thread::sleep_for(std::chrono::milliseconds(1));
                }
        }
private:
        std::list<int> message;
        std::mutex mtx;
 };

int main()
{
    
    
        A a;
        std::thread th1(&A::inQueue,&a);
        std::thread th2(&A::outQueue,&a);
        th1.join();
        th2.join();
        return 0;
}

6)单例模式在线程中的使用

#include <iostream>
#include<thread>
#include<mutex>

using namespace std;

std::mutex mtxRes;
//单例目的:即使多个线程被创建,也要保证只创建一个对象,所以创建多线程创建对象时,要做互斥量条件判断!!!
class A
{
    
    
private:
        A(){
    
    cout<<"A conctructor---"<<endl;}
private:
        static A* m_instance; //声明一个静态私有类指针变量
public:
        static A* getInstance()
        {
    
    
                if(m_instance == nullptr) //多个线程,为了提升速度(双重锁定)
                {
    
    
                        std::unique_lock<std::mutex> uniquelock(mtxRes);
                        if(m_instance == nullptr)
                        {
    
    
                                m_instance = new A();
                                static garb cl;//为了程序退出后,能够正常删除m_instance
                        }
                }
                return m_instance;
        }
        void test(void)
        {
    
    
                cout<<"test------"<<endl;
        }
        class garb //为了能正常delete m_instance,而设计的内部类
        {
    
    
        public:
                ~garb()
                {
    
    
                        if(A::m_instance != nullptr)
                        {
    
    
                                delete A::m_instance;
                                A::m_instance = nullptr;
                        }
                }
        };
};

A* A::m_instance = nullptr;


void func(void)
{
    
    
        cout<<"-----开始单例模式创建--------"<<endl;
        A::getInstance()->test();
        cout<<"-----单例模式创建完成--------"<<endl;
}

int main()
{
    
    
        // A::getInstance()->test();
        std::thread th1(func);
        std::thread th2(func);        
        th1.join();
        th2.join();

        return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_30143193/article/details/132533772