c++11线程

原文: http://www.codeproject.com/Articles/598695/Cplusplus11-threads-locks-and-condition-variables

C++11 threads, locks and condition variables
C++11 线程,锁和条件变量

This article is a walk-through the C++11 support for threads and synchronization mechanisms (mutexes and condition variables).
这篇文章主要是介绍C++11对线程和同步机制(互斥锁和条件变量)的支持。

1.线程(Threads)
C++11类库中引入了std::thread类,目的是在语言层面对线程操作提供支持。std::thread可以在函数,lambda表达式中使用,另外它还允许你为线程函数传递任何参数。

#include <thread>
 
void func()
{
   // do some work
}
 
int main()
{
   std::thread t(func);
   t.join();
 
   return 0;
}

在这个例子里 t 是thread对象,func()表示在线程环境下运行的函数。join()方法的调用,可以理解为,主线程main()阻塞在join()处,直到线程函数退出才继续运行。当然,func函数可以传递任何你需要的参数。

void func(int i, double d, const std::string& s)
{
    std::cout << i << ", " << d << ", " << s << std::endl;
}
 
int main()
{
   std::thread t(func, 1, 12.50, "sample");
   t.join();
 
   return 0;
}

上面可以看到,我们可以以值传递的方式来传递任何参数,但是,如果我们想要传引用的话,需要是用std::ref或std::cref,参考下面的例子。

void func(int& a)
{
   a++;
}
 
int main()
{
   int a = 42;
   std::thread t(func, std::ref(a));
   t.join();
 
   std::cout << a << std::endl;
 
   return 0;
}

程序输出43,如果没有使用std::ref的话则打印42。

处理join方法外,thread还提供另外两个操作
1)swap 交换两个线程句柄(好像在实际项目中没啥卵用,有实际应该过的朋友可以来补充)
2)detach 允许线程脱离线程对象独立运行,detach后的线程是无法join(wait)到他的返回的;

int main()
{
    std::thread t(funct);
    t.detach();
 
    return 0;
}

另外值得提一下的是关于线程异常的问题,如果线程函数抛出异常,是不能被捕获的。

try
{
    std::thread t1(func);
    std::thread t2(func);
 
    t1.join();
    t2.join();
}
catch(const std::exception& ex)
{
    std::cout << ex.what() << std::endl;
}

但当线程产生异常时,我们可以在线程中捕获它,将其暂时存放,而在稍后的时候对异常进行处理。

std::mutex                       g_mutex;
std::vector<std::exception_ptr>  g_exceptions;

void throw_function()
{
   throw std::exception("something wrong happened");
}

void func()
{
   try
   {
      throw_function();
   }
   catch(...)
   {
      std::lock_guard<std::mutex> lock(g_mutex);
      g_exceptions.push_back(std::current_exception());
   }
}

int main()
{
   g_exceptions.clear();

std::thread t(func);
   t.join();

for(auto& e : g_exceptions)
   {
      try
      {
         if(e != nullptr)
         {
            std::rethrow_exception(e);
         }
      }
      catch(const std::exception& e)
      {
         std::cout << e.what() << std::endl;
      }
   }

return 0;
}

2.锁(Lock)

在上面的例子中我们需要同步控制变量g_exceptions的访问,以确保同事只用一个线程修改(push)这个变量。
C++11中提供了4中同步控制的方法:
1)

时间: 2024-07-28 16:10:24

c++11线程的相关文章

C++11线程指南(二)--Lambda线程实现

1. Thread with lambda function 基于前一章中的Lambda程序,我们进行了扩展,当前创建5个线程. #include<iostream> #include<thread> #include<vector> #include<algorithm> int main() { std::vector<std::thread> threadVec; for(int i=0; i<5; ++i){ threadVec.p

c++11 线程

转自:http://www.justsoftwaresolutions.co.uk/threading/multithreading-in-c++0x-part-3.html 是个just的c++库.和c11很像. 用成员函数来作线程函数,需要传入额外的对象值.如果需要传入参数,接在头两个参数后面. 用引用而不同拷贝对象,需要调用 std::ref ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <thread> #include

C++11线程指南(四)--右值引用与移动语义

1. 按值传递 什么是按值传递? 当一个函数通过值的方式获取它的参数时,就会包含一个拷贝的动作.编译器知道如何去进行拷贝.如果参数是自定义类型,则我们还需要提供拷贝构造函数,或者赋值运算符来进行深拷贝.然而,拷贝是需要代价的.在我们使用STL容器时,就存在大量的拷贝代价.当按值传递参数时,会产生临时对象,浪费宝贵的CPU以及内存资源. 需要找到一个减少不必要拷贝的方法.移动语义就是其中一种. 2. 右值引用 此处介绍右值引用的目的,是为了实现后面的移动语义. 右值引用使得我们可以分辨一个值是左值

C++11线程指南(七)--死锁

1. 死锁 在多个mutex存在的时候,可能就会产生死锁. 避免死锁的一个最通用的方法是,总是按照相同的顺序来lock the two mutexes, 即总是先于mutex B之前lock mutex A,这样就不会有死锁的可能.有时,这种方法很简单实用,当这些mutexes用于不同的目标.但是,当mutexes用于包含相同类的一个实例时,就不是那么容易了. 例如,如下面程序所示,相同类的两个实例之间交互数据.为了保证数据交互不换并发影响,两个实例都使用mutex进行保护.但是当mutex被嵌

C++11线程指南(五)--线程的移动语义实现

1. 线程的移动语义实现 基于前面几章介绍的移动语义,我们用它来实现线程. #include <iostream> #include <thread> #include <vector> #include <algorithm> #include <cassert> int main() { std::vector<std::thread> workers; for (int i = 0; i < 5; i++) { auto

c++11 线程:让你的多线程任务更轻松

英文原文:C++ 11 Threading: Make your (multitasking) life easier 转载:http://www.oschina.net/translate/cplusplus-11-threading-make-your-multitasking-life 介绍 本文旨在帮助有经验的Win32程序员来了解c++ 11线程库及同步对象 和 Win32线程及同步对象之间的区别和相似之处. 在Win32中,所有的同步对象句柄(HANDLE)是全局句柄.它们可以被共享

C++11线程指南(七)--资源竞争条件

1. 接口设计1 下面例子使用vector实现了一个栈.两个线程轮流从中弹出元素. #include <iostream> #include <thread> #include <mutex> #include <string> #include <vector> std::mutex myMutex; class Stack { public: Stack() {}; ~Stack() {}; void pop(); int top() { r

c++11线程之条件变量condition_variable(二)

题目:编写一个程序,开启3个线程,这3个线程的ID分别为A.B.C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示:如:ABCABC-.依次递推. 采用C++11实现: [cpp] view plaincopyprint? #include<iostream> #include<thread> #include<mutex> #include<condition_variable> using namespace std; mut

《java.util.concurrent 包源码阅读》11 线程池系列之ThreadPoolExecutor 第一部分

先来看ThreadPoolExecutor的execute方法,这个方法能体现出一个Task被加入到线程池之后都发生了什么: public void execute(Runnable command) { if (command == null) throw new NullPointerException(); /* 如果运行中的worker线程数少于设定的常驻线程数,增加worker线程,把task分配给新建的worker线程 */ int c = ctl.get(); if (worker