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中,所有的同步对象都是栈(stack)对象,这意味着它们必须是可“分离(detached)”的(如果支持“分离”的话)以便能够被栈框架(stack frame)所析构。如果大量对象应该分离而你没有,那么它们便会无法实现自己的行动,而毁掉你的原本计划。(译者注:在pthread中,线程有joinable和unjoinable之分,具有joinable的线程在线程结束时,不会清空该线程所占用的栈空间,通常的做法是在pthrea_create创建线程后,再调用pthread_join(有点waitforsingleobject的意思)才会清空,而unjoinable的属性的线程在线程结束时,就会自动清空所占用空间)

所有的c++11同步对象都有一个native_handle()成员,它返回具体实现句柄(在win32,它就是一个handle)



背景知识

我也是c++11线程的新手。你需要自己去了解win32同步相关知识。这里可能不是合适的同步技术的教程,而是一个C++11机制的快速引导,以便对你所指定的计划有所帮助。



简单成就完美



一个简单例子:启动一个线程,然后等它结束:


1

2

3

4

5

6

7

8

void foo()

  {

  }

void func()

  {

  std::thread t(foo); // Starts. Equal to CreateThread.

  t.join();  // Equal to WaitForSingleObject to the thread handle.

  }

与win32线程不同,你可以在这里传递参数:


1

2

3

4

5

6

7

8

9

void foo(int x,int y)

  {

  // x = 4, y = 5.

  }

void func()

  {

  std::thread t(foo,4,5); // Acceptable.

  t.join(); 

  }

这样,通过传递‘this’指针给std::thread让成员函数成为一个线程,变成了一件很简单的事情.如果std::thread得以析构,而你没有调用join(),它将会异常终止。脱离c++封装运行线程:


2

3

4

5

6

7

8

9

void foo()

  {

  }

void func()

  {

      std::thread t(foo);

      // 在这里已经调用了detach方法,c++对象从win32对象中脱离出来,如果此时还调用join方法,就会抛出std::system_error()

      t.detach();

  }

除了join(),detach()方法,还有joinable(),get_id(),sleep_for(),sleep_until().它们都是自解释的,很好理解。



使用互斥(Mutex)

std::mutex与win32的临界区(cirtical section)很类似。lock()如同EnterCriticalSectionunlock如同LeaveCriticalSectiontry_lock则像TryEnterCriticalSection

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

std::mutex m;

int j = 0;

void foo()

  {

  m.lock();        // 进入临界区域

  j++;

  m.unlock();      // 离开

  }

void func()

  {

  std::thread t1(foo);

  std::thread t2(foo);

  t1.join();

  t2.join();

 // j = 2;

}



如上,你在lock一个 std::mutex 对象之后必须解锁(unlock)。如果你已经对其加锁,你不能再次lock。这与win32 不同,如果你已经在临界区(critical section)里,再次 EnterCriticalSection不会失败,但是会增加一个计数。

前面提到不能对std::mutex重复lock。这里有std::recursive_mutex(谁发明的这名字),它的行为则与临界区(critical section)相似,可以重复lock。

?


1

2

3

4

5

6

7

8

9

std::recursive_mutex m;

void foo()

  {

  m.lock();

  m.lock(); // now valid

  j++;

  m.unlock();

  m.unlock(); // don‘t forget!

  }

此外,还有 std::timed_mutexstd::recursive_timed_mutex,他们提供 try_lock_for/ try_lock_until方法,允许你等待一个lock,直到超时,或者达到定义的时间。



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

时间: 2024-11-03 20:58:39

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线程指南(七)--死锁

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

C++11线程,亲合与超线程

原作者:Eli Bendersky http://eli.thegreenplace.net/2016/c11-threads-affinity-and-hyperthreading/ 背景与简介 多年来,C与C++标准将多线程及并发处理排斥在外--在"目标机器依赖"世界的阴影之中,以"抽象机器"为目标的标准不包括它.在堆积如山,涉及并发的邮件列表及新闻组提问中,直接而冷血的"C++不知道线程是什么"的回答将永远提醒着这个过去. 不过这一切随着C

线程、进程、多线程、多进程

http://blog.csdn.net/lishenglong666/article/details/8557215 线程进程的联系和区别 定义: 进程是程序在计算机上的一次执行活动,是系统进行资源分配和调度的一个独立单位:  线程是进程的一个实体,是cpu调度和分派的基本单位,他是比进程更小的能独立运行的基本单位:线程自己基本上不拥有系统资源,只用有点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),一个线程可以创建和撤销另一个线程: 线程与进程的关系: 1)     一个线程只能属于

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线程

原文: http://www.codeproject.com/Articles/598695/Cplusplus11-threads-locks-and-condition-variables C++11 threads, locks and condition variablesC++11 线程,锁和条件变量 This article is a walk-through the C++11 support for threads and synchronization mechanisms (

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

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

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

线程的概念和多线程模子

线程的根本概念 引入过程的目标,是为了使多道程序并发履行,以进步资本应用率和零碎吞吐量:而引入线程,则是为了减小程序在并发履行时所支付的时空开支,进步操作零碎的并发功能.线程最直接的了解就是"轻量级过程",它是一个根本的CPU履行单位,也是程序履行流的最小单位,由线程ID.程序计数器.存放器聚集和客栈构成.线程是过程中的一个实体,是被零碎自力调剂和分配的根本单元,线程本人不具有零碎资本,只具有一点在运转中必弗成少的资本,但它可与同属一个过程的其他线程共享过程所具有的全体资本.一个线程可