c++11&14-多线程要点汇总

2020-06-03 11:00:35于丽

在C++11以前,C++的多线程编程均需依赖系统或第三方接口实现,一定程度上影响了代码的移植性。C++11中,引入了boost库中的多线程部分内容,形成C++标准,形成标准后的boost多线程编程部分接口基本没有变化,这样方便了以前使用boost接口开发的使用者切换使用C++标准接口,很容易把boost接口升级为C++标准接口。

我们通过如下几部分介绍C++11多线程方面的接口及使用方法。

1. std::thread

std::thread为C++11的线程类,使用方法和boost接口一样,非常方便,同时,C++11的std::thread解决了boost::thread中构成参数限制的问题,我想这都是得益于C++11的可变参数的设计风格。

我们通过如下代码熟悉下std::thread使用风格:

//c11.cpp
#include <iostream>
#include <thread>
void threadfun1()
{
 std::cout << "threadfun1 - 1rn" << std::endl;
 std::this_thread::sleep_for(std::chrono::seconds(1));
 std::cout << "threadfun1 - 2" << std::endl;
}
void threadfun2(int iParam, std::string sParam)
{
 std::cout << "threadfun2 - 1" << std::endl;
 std::this_thread::sleep_for(std::chrono::seconds(5));
 std::cout << "threadfun2 - 2" << std::endl;
}
int main()
{
 std::thread t1(threadfun1);
 std::thread t2(threadfun2, 10, "abc");
 t1.join();
 std::cout << "join" << std::endl;
 t2.detach();
 std::cout << "detach" << std::endl;
}

注意编译时要使用:g++ c11.cpp -lpthread

运行结果:

threadfun1 - 1
threadfun2 - 1
threadfun1 - 2
join
detach

2. std::atomic

std::atomic为C++11封装的原子数据类型。
什么是原子数据类型?从功能上看,简单地说,原子数据类型不会发生数据竞争,能直接用在多线程中而不必我们用户对其进行添加互斥资源锁的类型。从实现上来看,我们可以理解为这些原子类型内部自己加了锁。

我们下面通过一个测试例子说明原子类型std::atomic的特点。

我们使用10个线程,把std::atomic类型的变量iCount从10减到1。

//c11.cpp
#include <thread>
#include <atomic>
#include <stdio.h>
#include <iostream>
#include <list>
std::atomic<bool> bIsReady(false);
std::atomic<int> iCount(10);
void threadfun1()
{
 if (!bIsReady) {
  std::this_thread::yield();
 }
 while (iCount > 0)
 {
  printf("iCount:%drn", iCount--);
 }
}
int main()
{
 std::list<std::thread> lstThread;
 for (int i = 0; i < 10; ++i)
 {
  lstThread.push_back(std::thread(threadfun1));
 }
 for (auto& th : lstThread)
 {
  th.join();
 }
}

运行结果:

iCount:10
iCount:9
iCount:8
iCount:7
iCount:6
iCount:5
iCount:4
iCount:3
iCount:2
iCount:1

从上面的结果可以看到,iCount的最小结果是1,没有出现小于等于0的情况,大家可以把iCount改成100甚至1000看看,可能会更直观一点。