C++多线程进阶

  • ​​unique_lock三大参数对象​​
  • ​​condition_variable条件变量​​
  • ​​async&future异步任务​​
  • ​​packaged_task任务打包​​
  • ​​promise赋值取用​​

unique_lock三大参数对象

adopt_lock:表示已经lock了,无需再次lock了

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

std::mutex my_mutex;
void func01() {
my_mutex.lock();
std::lock_guard<std::mutex> g(my_mutex, std::adopt_lock);
}
int main() {
thread t1(func01);
return 0;
}

try_to_lock():再次之前没有锁,这个函数进行锁,如果锁了,返回异常

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

std::mutex my_mutex;
void func01() {
// my_mutex.lock();加了锁会报错
std::lock_guard<std::mutex> g(my_mutex, std::try_to_lock);
if (g.owns_lock()) {
// 查看是否拿到了锁
}
}
int main() {
thread t1(func01);
return 0;
}

condition_variable条件变量

线程执行的条件关键字

wait():等待条件满足才执行下面的数据。如果第二个参数是false,那么wait()将解锁互斥量,并堵塞到本行,堵塞到其他某个线程调用notify_one成员函数为止,此后,wait不断尝试获取互斥量锁

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

std::mutex my_mutex;
std::condition_variable my_con;
int a = 1;
void func01() {
for (int i = 0; i < 1000; i++) {
std::lock_guard<std::mutex> g(my_mutex);
my_con.wait(g, [&a] {
if (a == 1) {
return true;
}
});
}
}

notify_one():尝试唤醒一个正在wait的线程

void func02() {
for (int i = 0; i < 1000; i++) {
std::lock_guard<std::mutex> g(my_mutex);
std::cout << "yes" << std::endl;
notify_one();
}
}

notify_all():尝试唤醒多个正在wait的线程

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

std::mutex my_mutex;
std::condition_variable my_con;
int a = 1;
void func01() {
for (int i = 0; i < 1000; i++) {
std::lock_guard<std::mutex> g(my_mutex);
my_con.wait(g, [&a] {
if (a == 1) {
return true;
}
});

}
}
void func02() {
for (int i = 0; i < 1000; i++) {
std::lock_guard<std::mutex> g(my_mutex);
std::cout << "yes" << std::endl;
notify_all();
}
}
int main(int argc, char const* argv[]) {
std::thread t1_1(func01);
std::thread t1_2(func01);
std::thread t2(func02);
t1.join();
t2.join();
return 0;
}

async&future异步任务

async, future创建后台任务并返回值,async是个函数模板,用来启动一个异步任务(线程入口函数),返回一个future对象

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

int func() {
std::cout << std::this_thread::get_id() << std::endl;
return 5;
}
int main(int argc, char const* argv[]) {
std::cout << std::this_thread::get_id() << std::endl;
// 此程序意味着该线程在async处就开始创建
std::future<int> result = std::async(func);
std::cout << result.get() << std::endl;
return 0;
}
/*output:
25224
68260
5
*/

参数:std::launch::deferred
意义:表示线程入口函数调用被延迟到std::future的wait()或者get()函数调用时才执行,如果没有wait或者get,线程不会被创建;如果创建了,也是在主线程调用的线程入口函数.

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

int func() {
std::cout << std::this_thread::get_id() << std::endl;
return 5;
}
int main(int argc, char const* argv[]) {
std::cout << std::this_thread::get_id() << std::endl;
std::future<int> result = std::async(func);
// 此程序意味着该线程在async处就开始创建
std::cout << result.get() << std::endl;
return 0;
}
/*output:
74264 如果创建了,也是在主线程调用的线程入口函数.
74264
5
*/

参数:std::launch::async
意义:与默认函数相同

packaged_task任务打包

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

/*
打包方法:
std::packaged_task<返回值(参数)> 类对象(入口函数);
*/
int func(int arg) {
int num = arg + 1;
std::cout << "this is a thread: " << std::this_thread::get_id() << std::endl;
return num;
}
int main() {
std::packaged_task<int(int)> mypack(func);
// 以类对象作为线程调用的入口
std::thread t1(std::ref(mypack), 1);
t1.join();
std::future<int> res = mypack.get_future();
std::cout << res.get() << std::endl;

// 把打包的类对象放入容器中
std::vector<std::packaged_task<int(int)>> mytask;
mytask.push_back(std::move(mypack));

// 把打包的类对象从容器中拿出
std::packaged_task<int(int)> mypt;
auto iter = mytask.begin();
mypt = std::move(*iter);
mytask.erase(iter);

// 执行类对象打包的函数
std::thread t2(std::ref(mypt), 1);
t2.join();
std::future<int> re = mypt.get_future();
std::cout << re.get() << std::endl;
return 0;
}

promise赋值取用

我们能够在某个线程中给他赋值,然后我们可以在其他线程中,把这个值取出来用

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

void func(std::promise<int>& tp, int num) {
int res = 10;
tp.set_value(res);
return;
}
void func(std::future<int>& tp) {
int res = 10;
tp.set_value(res);
return;
}
int main() {
std::promise<int> mypro;
std::thread t1(func, std::ref(mypro), 180);
t1.join();
// 获取结果值
std::future<int> ful = mypro.get_future();
// auto res = ful.get();
// std::cout << res << std::endl;

// 也可以利用future的返回值做参数
std::thread t2(func, std::ref(ful));
t2.join();
// 获取结果值
std::future<int> fup = ful.get_future();
return 0;
}

溜了溜了,下一篇重点来介绍介绍future的成员函数