【摘要】 线程的创建
#include<thread>
void func(){}
std::thread t(func);
Join函数将会阻塞线程,直到线程函数执行结束。如果不希望线程被阻塞执行,可以调用线程的detach()方法,将线程和对象分离,当前线程不会阻塞。
线程不能赋值,但是可以移动;
std::thread t(func);
std::thread t1…
线程的创建
#include<thread>
void func(){}
std::thread t(func);
Join函数将会阻塞线程,直到线程函数执行结束。如果不希望线程被阻塞执行,可以调用线程的detach()方法,将线程和对象分离,当前线程不会阻塞。
线程不能赋值,但是可以移动;
std::thread t(func);
std::thread t1(std::move(t));
线程对象t将不再不代表任何线程。
注意线程对象的声明周期,确保函数执行的过程中,thread的对象仍然是存在的。可以使用join或者detach。
线程的基本使用方法
获取线程的id和cpu的核心
std::thread t(func);
t.get_id()———>线程的id
std::thread::hardware_concurrency()—->cpu的核心数
线程休眠
std::this_thead::sleep_for(std::chrono::seconds(3));
线程互斥量
std::mutex:独占的互斥量,不能递归使用
std::timed_mutex:带超时的独占互斥量,不能递归使用
std::recursive_mutex:递归互斥量,不带超时
std::recursive_timed_mutex:带超时的递归互斥量
1.std::mutex
std::mutex g_lock;
g_lock.lock();
…………..
g_lock.unlock();
{
std::lock_guard<std::mutex> lg(g_lock);
}
2.递归独占互斥量std::recursive_mutex
递归互斥量运行同一个线程多次获得该互斥锁,用来解决同一线程需要多次获取互斥量时的死锁问题。
3.带有超时互斥量std::timed_mutex和std::recusive_timed_mutex
std:teime_mutex比std::mutex多了两个接口:try_lock_for和try_lock_until
if(mutex.try_lock_for(timeout)
条件变量
conditon_variable,配合std::unique_lock<std::mutex> 进行wait操作。
condition_variable_any,和任意带有lock、unlock语义的mutex搭配使用,效率比conditional_variable差很多。
1)拥有条件变量的线程获取互斥量
2)循环检查某个条件,如果条件不满足,则阻塞直到条件满足;如果满足,继续执行。
3)某个线程满足条件执行完后调用notify_one或notify_all唤醒一个或者所有的等待线程。
std::lock_guard<std::mutex> locker(m_mutex);
while(IsFull())
m_notFull.wait(m_mutex);
m_notEmpty.notify_one();
wait还可以接受条件:
m_notFull.wait(locker,[this]{return !IsFull()});
wait的时候会释放锁,但是notify,notifyall的时候会获取锁。
std::unique_lock它可以随时释放锁。
std::unque_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker,[this]{return !m_queue.empty();});
原子量
std::atomic<int> value;
call_once/once_flag的使用
call_once确保在多线程情况下,被调用一次。
std::once_flag flag;
void do_once(){
std::call_once(flag,[](){std::cout<<“Called once”);
}
异步操作
std::future->作为异步结果的传输通道;
std::promise->将数据和future绑定起来,方便线程赋值。
std::package_task用来包装一个可调用对象,将函数和future绑定起来,方便异步调用。
std:future
获取线程的指向结果,通过查询future的状态来获取异步操作的结果。future只能move不能拷贝,如果放到容器,必须使用shared_future
future_status有如下的3种状态:
1.deferred,异步还没有开始
2.Ready,异步操作已经完成
3.Timeout,异步操作超时
status =future_wait_for(std::chrono::seconds(1));
std::future_status status;
std::promise
std::promise<int> pr;
std::thread t([](std::promise<int>& p){p.set_value_at_thread_exit(9);}, std::ref(pr));
std::future<int> f=pr.get_future();
auto r=f.get();
std::package_task
包装了一个可调用对象的包装类(如function/lambda/bind),将函数和future绑定,以便异步调用,promise保存了一个共享状态的值。
std::packaged_task<int()> task([](){return 7});
std::thread t1(std::ref(task));
std::futrue<int> f1=task.get_future();
auto r1=f1.get();
线程异步操作函数async
std::async比std::promise更高一层,异步任务返回的结果保存在future中,当需要获取异步任务的是,需要调用future.get(),如果仅仅等待执行完成,调用future.wait
有两种策略:
std::launch::async:调用async的时候开始创建线程
std::launch::defered:延迟加载方式线程,调用async时不创建线程,直到线程get或者wait时才创建线程。
std::future<int> f1=std::async(std::launch::async,[](){});
文章来源: blog.csdn.net,作者:珠峰之巅-程序员,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/CodeMyDream/article/details/116381832