C++多线程

多线程

一,线程状态·

       thread.join() -------------- 阻塞当前线程thread,直到thread执行完成;

       thread.detach() ----------使得当前线程脱离主线程的控制,该线程的资源由后台进程回收资源;

       thread.joinable() ---------- 判断线程是否可以join或者detach;

二,线程创建写法

       普通函数作为线程参数

       可调用对象作为线程参数-----例如一个类重载operator()

       lambda做为线程参数

三,线程传参的坑

       1,传递临时对象作为线程参数

             参数传递时应该显示构造对象,而不是依靠编译器隐士类型转换 例如char* -> string

             如果是一般数据类型建议使用值传递,因为有可能主线程早于子线程结束,导致内存失效

       2,传递类对象作为线程参数

             往线程入口函数传递类类型对象作为参数时不管是否以 引用接受,都一概采用复制对象的方式传递

            所以当我们需要修改某个对象的时候一般需要使用 std::ref(); eg:std::thread m_thread(&A::func(),&a,1);

            或者 std::ref(a);

             

互斥量

 锁

void Push(){

    mutex.lock();
    //.........去干一些事
    mutex2.lock();
}

void Pop(){

    mutex2.lock();
    //.....去干一些事
    mutex.lock();
}

上面代码就是一个死锁案例,所以为了防止造成死锁,一般在加锁的时候要按顺序加锁。

1,lock函数模板

     同时处理多个锁,解决加锁顺序问题而导致的死锁

2,lock_guard类模板

     lock_guard<std::mutex> sbguard(m_mutex,std::adopt_lock); // 表示不要再次lock,只需要unlock即可,但前提是先锁住

3,unique_lock类模板

    unique_lock<std::mutex> sbguard(m_mutex,std::adopt_lock); // 表示不要再次lock,只需要unlock即可,但前提是先锁住

    unique_lock<std::mutex> sbguard(m_mutex,std::try_to_lock);//尝试进行加锁,即便没有加锁成功也会返回,但不能提前加锁


std::unique_lock<std::mutex> sbguard(m_mutex,std::try_to_lock);

//owns.lock() //判断是否为主动加锁
if(sbguard.owns_lock()){
    
    //加锁成功
}else{
    
    //没有加锁成功
}

 unique_lock<std::mutex> sbguard(m_mutex,std::defer_lock); 初始化一个mutex,但是不加锁,如果提前加锁程会报异常

 unique_lock的成员函数

     1.lock(),unlock() ---  unique_lock可以随时加锁解锁,但lock_guard不行;

     2.try_lock(),尝试加锁,如果加锁成功返回true否则false;

     3,release(),解除unique_lock()与mutext的关联。 eg:

//1.lock()
{
    std::unique_lock<std::mutex> sbguard(mutex,std::defer_lock);
    sbgurad.lock();
}

//2,try_lock()
{
    std::unique_lock<std::mutex> sbguard(mutex,std::defer_lock); //不会阻塞
    
    if(sbguard.try_lock() == true){
        
        //拿到锁
    }else{
        //没有拿到锁
    }
}
//3,release()

{
    std::unique_lock<std::mutex> sbguard(mutex,std::defer_lock);
    std::mutex* p_mtx = sbguard.release(); //现在这个锁就需要程序员自己管理
}

 条件变量

condition_variable --是一个类,只能接受unique_lock,必须配合互斥量

condition_variable_any --是一个类,可以接受任意类型的锁

wait() ,wait_for(),wait_until(),notify_one(),notify_all(),

std::condition_variable m_cond;

/*.....
.......
*/

//消费者
while(true){

    std::unique_lock<std::mutex> sbgurad(mutex);
    m_cond.wait(sbguard,[]{return false}) // or return true;
    //..........
}

//生产者
for(int i = 0; i < 100; ++i){
   
    std::unique_lock<std::mutex> sbgurad(mutex);
    queue.push_back(i);
    m_cond.notify_one();

}

1,如果第二个参数为true,则wait直接返回

2,如果第二个参数为false,则wait解锁互斥量并堵塞直到另一个线程调用notify_one()

3,如果第二个参数为空,相当于false

4,notify_one() 通知某一个线程,notify_all()通知所有线程

5,wait_for(mutex,std::chrono::duration<rep,den>) 当线程被通知或者超出时间段之后wait_for()返回

5,wait_until()到达某个时间点或者被通知wait_until()返回

6,  cv.wait_for(mutex,std::chrono::seconds(1) == std::cv_status::timeout),通过cv_status来判断是否超时

7, 为了防止虚假唤醒,务必做判断

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值