#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";
}
#多线程 C++11
于 2024-08-01 17:04:37 首次发布