C++使用thread类多线程编程

原文地址:https://blog.csdn.net/dcrmg/article/details/53912941

C++11中引入了一个用于多线程操作的thread类,简单多线程示例:


[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <thread>  
  3. #include <Windows.h>  
  4.   
  5. using namespace std;  
  6.   
  7. void thread01()  
  8. {  
  9.     for (int i = 0; i < 5; i++)  
  10.     {  
  11.         cout << "Thread 01 is working !" << endl;  
  12.         Sleep(100);  
  13.     }  
  14. }  
  15. void thread02()  
  16. {  
  17.     for (int i = 0; i < 5; i++)  
  18.     {  
  19.         cout << "Thread 02 is working !" << endl;  
  20.         Sleep(200);  
  21.     }  
  22. }  
  23.   
  24. int main()  
  25. {  
  26.     thread task01(thread01);  
  27.     thread task02(thread02);  
  28.     task01.join();  
  29.     task02.join();  
  30.   
  31.     for (int i = 0; i < 5; i++)  
  32.     {  
  33.         cout << "Main thread is working !" << endl;  
  34.         Sleep(200);  
  35.     }  
  36.     system("pause");  
  37. }  


输出:



两个子线程并行执行,join函数会阻塞主流程,所以子线程都执行完成之后才继续执行主线程。可以使用detach将子线程从主流程中分离,独立运行,不会阻塞主线程:


[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <thread>  
  3. #include <Windows.h>  
  4.   
  5. using namespace std;  
  6.   
  7. void thread01()  
  8. {  
  9.     for (int i = 0; i < 5; i++)  
  10.     {  
  11.         cout << "Thread 01 is working !" << endl;  
  12.         Sleep(100);  
  13.     }  
  14. }  
  15. void thread02()  
  16. {  
  17.     for (int i = 0; i < 5; i++)  
  18.     {  
  19.         cout << "Thread 02 is working !" << endl;  
  20.         Sleep(200);  
  21.     }  
  22. }  
  23.   
  24. int main()  
  25. {  
  26.     thread task01(thread01);  
  27.     thread task02(thread02);  
  28.     task01.detach();  
  29.     task02.detach();  
  30.   
  31.     for (int i = 0; i < 5; i++)  
  32.     {  
  33.         cout << "Main thread is working !" << endl;  
  34.         Sleep(200);  
  35.     }  
  36.     system("pause");  
  37. }  

输出:


使用detach的主线程和两个子线程并行执行。


带参子线程


在绑定的时候也可以同时给带参数的线程传入参数:

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <thread>  
  3. #include <Windows.h>  
  4.   
  5. using namespace std;  
  6.   
  7. //定义带参数子线程  
  8. void thread01(int num)  
  9. {  
  10.     for (int i = 0; i < num; i++)  
  11.     {  
  12.         cout << "Thread 01 is working !" << endl;  
  13.         Sleep(100);  
  14.     }  
  15. }  
  16. void thread02(int num)  
  17. {  
  18.     for (int i = 0; i < num; i++)  
  19.     {  
  20.         cout << "Thread 02 is working !" << endl;  
  21.         Sleep(200);  
  22.     }  
  23. }  
  24.   
  25. int main()  
  26. {  
  27.     thread task01(thread01, 5);  //带参数子线程  
  28.     thread task02(thread02, 5);  
  29.     task01.detach();  
  30.     task02.detach();  
  31.   
  32.     for (int i = 0; i < 5; i++)  
  33.     {  
  34.         cout << "Main thread is working !" << endl;  
  35.         Sleep(200);  
  36.     }  
  37.     system("pause");  
  38. }  

输出跟上例输出一样:



多线程数据竞争


多个线程同时对同一变量进行操作的时候,如果不对变量做一些保护处理,有可能导致处理结果异常:

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <thread>  
  3. #include <Windows.h>  
  4.   
  5. using namespace std;  
  6.   
  7. int totalNum = 100;  
  8.   
  9. void thread01()  
  10. {  
  11.     while (totalNum > 0)  
  12.     {  
  13.         cout << totalNum << endl;  
  14.         totalNum--;  
  15.         Sleep(100);  
  16.     }  
  17. }  
  18. void thread02()  
  19. {  
  20.     while (totalNum > 0)  
  21.     {  
  22.         cout << totalNum << endl;  
  23.         totalNum--;  
  24.         Sleep(100);  
  25.     }  
  26. }  
  27.   
  28. int main()  
  29. {  
  30.     thread task01(thread01);  
  31.     thread task02(thread02);  
  32.     task01.detach();  
  33.     task02.detach();  
  34.     system("pause");  
  35. }  

输出结果(部分):



有两个问题,一是有很多变量被重复输出了,而有的变量没有被输出;二是正常情况下每个线程输出的数据后应该紧跟一个换行符,但这里大部分却是另一个线程的输出。

这是由于第一个线程对变量操作的过程中,第二个线程也对同一个变量进行各操作,导致第一个线程处理完后的输出有可能是线程二操作的结果。针对这种数据竞争的情况,可以使用线程互斥对象mutex保持数据同步。

mutex类的使用需要包含头文件mutex:

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <thread>  
  3. #include <Windows.h>  
  4. #include <mutex>  
  5.   
  6. using namespace std;  
  7.   
  8. mutex mu;  //线程互斥对象  
  9.   
  10. int totalNum = 100;  
  11.   
  12. void thread01()  
  13. {  
  14.     while (totalNum > 0)  
  15.     {  
  16.         mu.lock(); //同步数据锁  
  17.         cout << totalNum << endl;  
  18.         totalNum--;  
  19.         Sleep(100);  
  20.         mu.unlock();  //解除锁定  
  21.     }  
  22. }  
  23. void thread02()  
  24. {  
  25.     while (totalNum > 0)  
  26.     {  
  27.         mu.lock();  
  28.         cout << totalNum << endl;  
  29.         totalNum--;  
  30.         Sleep(100);  
  31.         mu.unlock();  
  32.     }  
  33. }  
  34.   
  35. int main()  
  36. {  
  37.     thread task01(thread01);  
  38.     thread task02(thread02);  
  39.     task01.detach();  
  40.     task02.detach();  
  41.     system("pause");  
  42. }  

多线程中加入mutex互斥对象之后输出正常:

猜你喜欢

转载自blog.csdn.net/metal1/article/details/80284271