c++11 多线程

【摘要】 线程的创建
#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

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享