c++11特性里的多线程thread的用法

创建和启动一条C++线程就像在C++源码中添加线程头文件那么简便。我们来看看如何创建一个简单的带线程的HelloWorld:


    
    
  1. #include <iostream>
  2. #include <thread>
  3. using namespace std;
  4. //This function will be called from a thread
  5. //该函数将在一条线程中得到调用
  6. void call_from_thread()
  7. {
  8. cout << “hello world!” << endl;
  9. }
  10. int main()
  11. {
  12. //Launch a thread
  13. //启动一条线程
  14. thread t1(call_from_thread);
  15. //Join the thread with the main thread
  16. //和主线程协同
  17. t1.join();
  18. return 0;
  19. }

输出:Hello world!

在真实世界的应用程序中,函数“call_from_thread”相对主函数而言,独立进行一些运算工作。在上述代码中,主函数创建一条线程,并在t1.join()处等待t1线程运行结束。如果你在编码中忘记考虑等待一条线程结束运行,主线程有可能抢先结束它自己的运行状态,整个程序在退出的时候,将杀死先前创建的线程,不管函数“call_from_thread”有没有执行完。


我们通常希望一次启动多个线程,来并行工作。为此,我们可以创建线程组,而不是上面举例中那样创建一条线程。下面的例子中,主函数创建十条为一组的线程,并且等待这些线程完成他们的任务:


    
    
  1. #include <iostream>
  2. #include <thread>
  3. using namespace std;
  4. static const int num_threads = 10;
  5. void call_from_thread(int tid)
  6. {
  7. cout << "Launched by thread" <<tid<< endl;
  8. }
  9. int main()
  10. {
  11. thread t[num_threads];
  12. //Launch a group of threads 启动一组线程
  13. for ( int i = 0; i < num_threads;++i)
  14. {
  15. t[i] = thread(call_from_thread,i);
  16. }
  17. cout << "Launched from the main";
  18. //Join the threads with the main thread
  19. for ( int i = 0; i < num_threads;++i)
  20. {
  21. t[i].join();
  22. }
  23. return 0;
  24. }
说明:记住,主函数也是一条线程,通常叫做主线程,所以上面的代码实际上有11条线程在运行。在启动这些线程组之后,线程组和主函数进行协同(join)之前,允许我们在主线程中做些其他的事情。

在线程中使用带有形参的函数,是怎么一回事呢?C++11允许我们在线程的调用中,附带上所需的任意参数。

输出:

能看到上面的结果中,程序一旦创建一条线程,其运行存在先后秩序不确定的现象。程序员的任务就是要确保这组线程在访问公共数据时不要出现阻塞。事实上假定在你自己的机器上运行上面的代码,将会获得全然不同的结果,甚至是会输出些混乱的字符。原因在于,程序内的11条线程都在竞争性地使用stdout这个公共资源。
要避免上面的问题,可以在代码中使用拦截器(barriers),如std:mutex,以同步(synchronize)的方式来使得一群线程访问公共资源,或者,如果可行的话,为线程们预留下私用的数据结构,避免使用公共资源。

            </div>

创建和启动一条C++线程就像在C++源码中添加线程头文件那么简便。我们来看看如何创建一个简单的带线程的HelloWorld:


  
  
  1. #include <iostream>
  2. #include <thread>
  3. using namespace std;
  4. //This function will be called from a thread
  5. //该函数将在一条线程中得到调用
  6. void call_from_thread()
  7. {
  8. cout << “hello world!” << endl;
  9. }
  10. int main()
  11. {
  12. //Launch a thread
  13. //启动一条线程
  14. thread t1(call_from_thread);
  15. //Join the thread with the main thread
  16. //和主线程协同
  17. t1.join();
  18. return 0;
  19. }

输出:Hello world!

在真实世界的应用程序中,函数“call_from_thread”相对主函数而言,独立进行一些运算工作。在上述代码中,主函数创建一条线程,并在t1.join()处等待t1线程运行结束。如果你在编码中忘记考虑等待一条线程结束运行,主线程有可能抢先结束它自己的运行状态,整个程序在退出的时候,将杀死先前创建的线程,不管函数“call_from_thread”有没有执行完。


我们通常希望一次启动多个线程,来并行工作。为此,我们可以创建线程组,而不是上面举例中那样创建一条线程。下面的例子中,主函数创建十条为一组的线程,并且等待这些线程完成他们的任务:


  
  
  1. #include <iostream>
  2. #include <thread>
  3. using namespace std;
  4. static const int num_threads = 10;
  5. void call_from_thread(int tid)
  6. {
  7. cout << "Launched by thread" <<tid<< endl;
  8. }
  9. int main()
  10. {
  11. thread t[num_threads];
  12. //Launch a group of threads 启动一组线程
  13. for ( int i = 0; i < num_threads;++i)
  14. {
  15. t[i] = thread(call_from_thread,i);
  16. }
  17. cout << "Launched from the main";
  18. //Join the threads with the main thread
  19. for ( int i = 0; i < num_threads;++i)
  20. {
  21. t[i].join();
  22. }
  23. return 0;
  24. }
说明:记住,主函数也是一条线程,通常叫做主线程,所以上面的代码实际上有11条线程在运行。在启动这些线程组之后,线程组和主函数进行协同(join)之前,允许我们在主线程中做些其他的事情。

在线程中使用带有形参的函数,是怎么一回事呢?C++11允许我们在线程的调用中,附带上所需的任意参数。

输出:

能看到上面的结果中,程序一旦创建一条线程,其运行存在先后秩序不确定的现象。程序员的任务就是要确保这组线程在访问公共数据时不要出现阻塞。事实上假定在你自己的机器上运行上面的代码,将会获得全然不同的结果,甚至是会输出些混乱的字符。原因在于,程序内的11条线程都在竞争性地使用stdout这个公共资源。
要避免上面的问题,可以在代码中使用拦截器(barriers),如std:mutex,以同步(synchronize)的方式来使得一群线程访问公共资源,或者,如果可行的话,为线程们预留下私用的数据结构,避免使用公共资源。

            </div>

猜你喜欢

转载自blog.csdn.net/monk1992/article/details/81661781