c++11 多线程

线程的创建

#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,[](){});

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值