#多线程 C++11

#include <iostream>
#include <future>
#include <numeric>
#include <vector>
#include <algorithm>
#include <chrono>


/*
*  std::thread 底层内容,创建线程
*  std::lock_guard RAII 简单上锁,析构解锁
*  std::unique_lock 复杂锁,可移动复制转移mutex,随时解锁,初始化设置锁开启机制(可延迟手动锁定)
*  std::condition_variable 控制线程执行顺序,wait在条件不满足时解锁lck后供其他线程执行,其他线*  程执行完毕,发出通知后,wait再继续上锁执行后续
*  std::async 封装了thread的创建,更高层的接口,返回了future
*  std::std::future 获取线程的异步执行结果,未来的结果,std::future_status 获取结果状态
*  std::promise 保存了一个共享状态的值,封装了future,传给线程函数,可以设置值,等待线程结束后获取值
*  std::packaged_task保存的是一个函数,通过future获取函数执行结果,async相当于是封装了这个
*/

void run_Async()
{
    std::mutex mutex;
    std::vector<std::future<int>> futures;
    std::promise<int> value; //传给线程函数,查看线程中数据;

    std::packaged_task<int()> task([&]() { return 1; });
    std::thread t(std::ref(task));
    std::future<int> v = task.get_future();
    auto n = v.get();


    int nCount = 0;

    for (auto i = 0; i <= 100; i++)
    {
        futures.push_back(std::async(std::launch::async,/*std::launch::deferred 延迟等待future::wait后执行*/
            [&i, &mutex,&nCount](std::promise<int>& p)
            {
                //async执行如下代码,会在创建时候运行,所以并不会按顺序执行nCount++ 从1到100
                //这里不适合做nCount++按顺序输出,适合做把这个值增大到100,因为线程间没有顺序关联,所以nCount不按线程顺序增大
                //deferred会按顺序等待线程输出,但在这里例子中失去了多线程并行意义,因为deferred根本没有创建新线程
                //还是在主线程上,只是调用了执行函数而已
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
                std::cout << std::this_thread::get_id() << std::endl;
                std::lock_guard<std::mutex> lock(mutex);
                nCount++;
                p.set_value(nCount);
                return nCount;

				//线程安全问题,准确性问题,数据共享问题
				//std::this_thread::sleep_for(std::chrono::milliseconds(100));
				int n = 0;
				{
					std::lock_guard<std::mutex> lock(mutex); //出{}后自动解锁
					nCount++;
					n = i;     //当前线程阻塞时,for循环已经在线程外修改了i,所以n输出不准确
				}
				return nCount; //当前线程执行到这里后,其他线程获取到锁修改了nCount,所以输出也不准确

				//效率问题for 100000
				/* std::vector<int> arr{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
				 auto n = std::accumulate(arr.begin(), arr.end(),1, std::multiplies<int>());
				 return n;*/
            }, std::ref(value)));
    }

    //async执行方式时,会创建新的线程
    //std::future.get()方法获取返回值,如果不等待,主线程依然会等待子线程结束之后再销毁
    //deferred执行方式,如果不等待,会直接返回,如果等待,只是调用了执行函数

    std::cout << value.get_future().get() << std::endl;
    for (auto& future : futures)
    {
        //future.wait();         //如果不需要获取结果wait即可

        auto val = future.get(); //等待执行完成后拿到结果
        std::cout << val << std::endl;
    }

    /*
    *  选择多线程执行是选择场景的,比如 http 这种需要同时进行的需求
    *  如果是单核CPU,并行不一定比单线程快,只是每个run貌似是同时的,反而每个run花费更多时间
    *  但是在多CPU下,明显会提高效率,是真正的并行
    *  因为跨线程需要耗费开销时间、空间资源,所以尽量减少跨线程的访问,比如共同修改主线程的变量地址
    * 
    *  如下代码在单CPU单线程就比多线程快
    */

    /*for (auto i = 0; i <= 100000; i++)
    {
        std::vector<int> arr{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
		auto n = std::accumulate(arr.begin(), arr.end(), 1, std::multiplies<int>());
        std::cout << n << std::endl;   
    } */
}

int main()
{
    run_Async();

    std::cout << "Hello World!\n";
}

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值