用C++11进行多线程开发

今天用c++写了一些多线程的代码,写之前感觉c线程同步中用到互斥锁,条件变量等使用起来比较麻烦,于是就自己把c中的互斥锁,还有条件变量封装了一遍,封完之后在c++11相关书中查看东西时,偶然发现原来我重复造了轮子,这些c++11早就为我们准备妥当了,哪还要自己去封。。。
接下来就总结一下,刚学来的c++11对多线程开发的知识

1.线程

(1)线程创建

c++11创建线程相当容易,只需将线程类std::thread创建并初始话即可
具体实例如下

#include <iostream>
#include <thread>

void thread_worker(int n)
{
    std::cout<<"n = "<<n<<std::endl;
}

int main(int argc,char **argv)
{
  std::thread t(thread_worker,5);//创建线程对象t
  t.join();阻塞线程t,直到其结束
  return 0;
}

注意编译时要加线程库 -pthread

(2)线程传参

上述代码中,我们在初始化线程对象t是,首先第一个参数为线程函数的函数指针,其次便是线程函数的参数,如果线程有多个参数的话,我们只需按照参数顺序直接一次写到线程函数指针之后即可,具体实例如下

#include <iostream>
#include <thread>
#include <string>

void thread_worker(int n,std::string s,int m)
{
    std::cout<<"n = "<<n<<std::endl;
    std::cout<<"s = "<<s<<std::endl;
    std::cout<<"m = "<<m<<std::endl;
}

int main(int argc,char **argv)
{
  std::thread t(thread_worker,5,"shreck",6);
  t.join();
  return 0;
}

(3)线程阻塞

(1)中线程对象的join成员函数会阻塞在那,知道线程执行完毕,用于回收线程结束状态,如果我们不想回收线程状态,可以直接调用detach使线程和对象分离,这样做的话我们就不会知道线程何时会执行完毕
具体实例如下

#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>

void thread_worker(int n,std::string s,int m)
{
    std::cout<<"n = "<<n<<std::endl;
    std::cout<<"s = "<<s<<std::endl;
    std::cout<<"m = "<<m<<std::endl;
}

int main(int argc,char **argv)
{
  std::thread t(thread_worker,5,"shreck",6);
  t.detach();
  sleep(1);
  return 0;
}

上述代码之所以要在分离之后暂停1s是因为我的机器老是主线程先于子线程执行,导致子线程还没打印呢,主线程以退出,对应的子线程也退出了(详细知识请查看我之前有关与线程总结的博文)

2互斥量

(1)std::mutex类

C++11使用互斥量,相比c变得十分简单,它将c互斥量的操作封装与std::mutex类中,该类具体使用如下

#include <iostream>
#include <string>
#include <thread>
#include <mutex>

int sum = 0;

std::mutex g_lock;  //创建互斥锁对象

void thread_worker(int thread_number)
{
    while(1)
    {
        g_lock.lock();//加锁
        sum++;
        std::cout<<"线程"<<thread_number<<":sum = "<<sum<<std::endl;
        g_lock.unlock();//解锁
    }
}

int main(int argc,char **argv)
{
  std::thread t1(thread_worker,1);
  std::thread t2(thread_worker,2);
  std::thread t3(thread_worker,3);
  t1.join();
  t2.join();
  t3.join();
  return 0;
}

(2)std::lock_guard类

除了std::mutex类之外,c++11还为我们提供了更好用,也更安全的互斥锁类std::lock_guard,这个类运用了RALL技术(利用c++的构造函数分配资源,析构函数来释放资源),使我们免去了(1)中释放锁的过程,要知道我们平时写程序,上完锁之后很可能忘记释放锁,这是很可怕的问题,所以为了安全起见,我们最好使用此类
其具体用法如下

#include <iostream>
#include <string>
#include <thread>
#include <mutex>

int sum = 0;

std::mutex g_lock;  //创建互斥锁对象

void thread_worker(int thread_number)
{
    while(1)
    {
        //用g_lock初始化此类
        std::lock_guard<std::mutex> guard(g_lock);
        sum++;
        std::cout<<"线程"<<thread_number<<":sum = "<<sum<<std::endl;
    }
}

int main(int argc,char **argv)
{
  std::thread t1(thread_worker,1);
  std::thread t2(thread_worker,2);
  std::thread t3(thread_worker,3);
  t1.join();
  t2.join();
  t3.join();
  return 0;
}

3.条件变量

C++11中同样也封装了对条件变量使用的类,在这里我只为大家介绍一种最通用的类

(1)std::condition_variable_any

使用实例如下

#include <thread>
#include <stdio.h>
#include <mutex>
#include <condition_variable>

int sum = 0;
std::mutex g_lock;
std::condition_variable_any condtion;
void work(int n)
{
    while(1)
    {
        std::lock_guard<std::mutex> guard(g_lock);
        sum++;
        printf("%d:被加到%d\n",n,sum);
        condtion.notify_one();

    }    
}

int main(void)
{
    std::thread t1(work,1);
    std::thread t2(work,2);
    std::thread t3(work,3);

    while(1)
    {
        std::lock_guard<std::mutex> guard(g_lock);
        //传入互斥锁g_lock
        condtion.wait(g_lock);
        while(sum > 0)
        {
            sum--;
        }

        printf("sum被减为sum = %d\n",sum);

    }    
    return 0;
}

4.总结

之前也会用到C++11的一些东西,但没有系统的查看,通过这次的教训,我想我们应该好好的看看c++11的新特性,以防止再次造轮子,同时c++11给我们的接口也更为简单好用

你可能感兴趣的:(线程,C语言,互斥锁,条件变量,C++11)