c++11 多线程基础

    在c++11中,c++标准库中就增加了关于多线程的一些操作,在此之前我们不得不调用系统底层的多线程函数,或者用第三方的线程库,多少还是有些不便,现在我们可以用标准库中的多线程函数来开发多线程程序了。下面就介绍一下基本的用法。

#include 
   
   
    
    
#include 
    
    
     
     

void thread_test(int a,int b)
{
    std::cout << "thread_test:a + b = " <<  a + b << std::endl;
}

int main()
{
    std::thread t1(thread_test,1,2);
    t1.join();
    return 0;
}
    
    
   
   

    不管从创建线程还是向线程传递参数都方便了很多。
    下面我们看一下锁的使用。
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
          std::queue 
         
           test_queue; std::mutex queu_mut; void thread_pop() { int i = 0; while(1) { std::lock_guard 
          
            mut(queu_mut); if (test_queue.size() > 0) { std::cout << "pop " << test_queue.front() << std::endl; test_queue.pop(); if (i == 5) { return; } i++; } } } void thread_push() { int i = 0; while(1) { std::lock_guard 
           
             mut(queu_mut); std::cout << "push " << i << std::endl; test_queue.push(i); sleep(1); if (i == 5) { return; } i++; } } int main() { std::thread t1(thread_pop); std::thread t2(thread_push); t1.join(); t2.join(); return 0; } 
            
           
          
        
       
       
      
      
     
     
    
    


    std::lock_guard是c++标准哭中的一个比较轻量级的一个锁,当我们生命一个std::lock_guard一个变量时会锁住互斥量,互斥量的释放实在它的析构函数中做的,因此当她出了它的作用域调用析构函数时会自动解锁,我们也不用担心因为程序因为异常或者其他的因素导致没有释放互斥量而造成死锁的情况了。注意上面的例子中所得范围仅限于while循环内,每次出whiile循环都会释放锁,如果把锁写在外面结果会大有不同。
   下面看一个线程间通信的例子:
     
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
          std::queue 
         
           test_queue; std::mutex queu_mut; std::condition_variable data_cond; //调用该函数地方必须要在锁的保护范围,该函数里面加锁会造成嵌套锁,从而死锁 bool isDataPrepare() { return test_queue.size() >= 5; } void thread_pop() { while(1) { std::unique_lock 
          
            lk(queu_mut); std::cout << "wait " << std::endl; data_cond.wait(lk,[] {return isDataPrepare();}); std::cout << "pop " << test_queue.front() << std::endl; test_queue.pop(); lk.unlock(); return; } } void thread_push() { int i = 0; while(1) { std::lock_guard 
           
             guard(queu_mut); test_queue.push(i); sleep(1); std::cout << "push " << i << std::endl; if (isDataPrepare()) { data_cond.notify_one(); return; } i++; } } int main() { std::thread t1(thread_pop); std::thread t2(thread_push); t1.join(); t2.join(); return 0; } 
            
           
          
        
       
       
      
      
     
     
    
    

    这里是一个类似于生产者消费着的例子,当我们在queue中存入6个元素的时候给通知另外一个线程去读取元素,这里用到了另外一种锁,这种锁和上面的锁相比用法比较灵活,我们可以手动解锁,控制锁的粒度.这里我们还用到了wait函数,我们来分析一下程序的运行过程,当我们启动两个线程,当然究竟哪个先启我们不能保证,当pop线程执行到wait时,会检查lambda表达式条件是否满足,如果条件不满足,将解锁互斥量,阻塞当前线程,当push线程通过notify_one函数通知,当pop线程收到通知时,线程从阻塞中苏醒,重新获取互斥量,也就是加锁,(通常我们等待的条件和通知线程的通知条件时一样的,如果不一样也没有什么意义,如果不一样我们通知时可能因为等待的条件已经满足,等待的线程收不到通知了),并且再次判断条件是否满足,如果满足wait返回继续持有该锁,往下走,当走到29行时,解锁互斥量,要注意,如果wait条件不满足时会解锁,否则该线程阻塞在这里并且不把锁释放掉,其他线得不到互斥量也会阻塞,因此我们这里用的是unique_lock,因为lock_guard没有提供手动解锁的方法,否则该线程因条件不满足而阻塞的时候将继续持有该锁,从而阻塞其他线程,这是我们最不想看到的。
   以上之时一些简单的用法,更多详细的资料看链接里的c++11并发编程指南: 点击打开链接,还有一本书, 点击打开链接

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值