| 头文件 |
#include<thread> 头文件中声明
命名空间统一在std
|
|
| 成员类型和成员函数 |
成员类型:
id native_handle_type
成员函数: Construct thread // 构造函数 Thread destructor // 析构函数 operator=// 赋值重载 get_id // 获取线程id joinable// 判断线程是否可以加入等待 join//Join thread (public member function ) 加入等待 detach//Detach thread (public member function ) 分离线程 swap//Swap threads (public member function ) 线程交换 native_handle// 获取线程句柄 hardware_concurrency // 检测硬件并发特性 swap (thread) Swap threads (function )
|
|
| std::thread 构造函数 |
#include<thread>
#include<chrono> using namespace std; void fun1(int n) //初始化构造函数 { cout << "Thread " << n << " executing\n"; n += 10; this_thread::sleep_for(chrono::milliseconds(10)); } void fun2(int & n) //拷贝构造函数 { cout << "Thread " << n << " executing\n"; n += 20; this_thread::sleep_for(chrono::milliseconds(10)); } int main() { int n = 0; thread t1; //t1不是一个thread thread t2(fun1, n + 1); //按照值传递 t2.join(); cout << "n=" << n << '\n'; n = 10; thread t3(fun2, ref(n)); //引用 thread t4(move(t3)); //t4执行t3,t3不是thread t4.join(); cout << "n=" << n << '\n'; return 0; } 运行结果: Thread 1 executing n=0 Thread 10 executing n=30
|
|
|
同、异步
CPP原子变量与线程安全
|
多线程资源竞争问题例如:
#include<iostream> #include<thread> using namespace std; const int N = 100000000; int num = 0; void run() { for (int i = 0; i < N; i++) { num++; } } int main() { clock_t start = clock(); thread t1(run); thread t2(run); t1.join(); t2.join(); clock_t end = clock(); cout << "num=" << num << ",用时 " << end - start << " ms" << endl; return 0; } 运行结果: num=143653419,用时 730 ms</span> 从上述代码执行的结果,发现结果并不是我们预计的200000000,这是由于线程之间发生冲突,从而导致结果不正确。 为了解决此问题,有以下方法: (1)互斥量。 例如:
#include<iostream> #include<thread> #include<mutex> using namespace std; const int N = 100000000; int num(0); mutex m; void run() { for (int i = 0; i < N; i++) { m.lock(); num++; m.unlock(); } } int main() { clock_t start = clock(); thread t1(run); thread t2(run); t1.join(); t2.join(); clock_t end = clock(); cout << "num=" << num << ",用时 " << end - start << " ms" << endl; return 0; } 运行结果: num=200000000,用时 128323 ms</span> 通过互斥量后运算结果正确,但是计算速度很慢,原因主要是互斥量加解锁需要时间。 互斥量详细内容 请参考C++11 并发之std::mutex。(2)原子变量。
#include<iostream> #include<thread> #include<atomic> using namespace std; const int N = 100000000; atomic_int num{ 0 };//不会发生线程冲突,线程安全 void run() { for (int i = 0; i < N; i++) { num++; } } int main() { clock_t start = clock(); thread t1(run); thread t2(run); t1.join(); t2.join(); clock_t end = clock(); cout << "num=" << num << ",用时 " << end - start << " ms" << endl; return 0; } 运行结果: num=200000000,用时 29732 ms</span> 通过原子变量后运算结果正确,计算速度一般。 原子变量详细内容 请参考C++11 并发之std::atomic。
|
|
|
#include<iostream> #include<thread> #include<chrono> using namespace std; int main() { thread th1([]() { //让线程等待3秒 this_thread::sleep_for(chrono::seconds(3)); //让cpu执行其他空闲的线程 this_thread::yield(); //线程id cout << this_thread::get_id() << endl; }); return 0; }
|
|
| 多线程传递参数 |
#include<iostream>
#include<thread> using namespace std; void show(const char *str, const int id) { cout << "线程 " << id + 1 << " :" << str << endl; } int main() { thread t1(show, "hello cplusplus!", 0); thread t2(show, "你好,C++!", 1); thread t3(show, "hello!", 2); return 0; } 运行结果: 线程 1: hello!
线程 2:你好,
线程 3 : hello cplusplus!
发现,线程 t1、t2、t3 都执行成功!
|
|
| join、detach |
#include<iostream>
#include<thread> #include<array> using namespace std; void show() { cout << "hello cplusplus!" << endl; } int main() { array<thread, 3> threads = { thread(show), thread(show), thread(show) }; for (int i = 0; i < 3; i++) { cout << threads[i].joinable() << endl;//判断线程是否可以join threads[i].join();//主线程等待当前线程执行完成再退出 } return 0; } 运行结果: hello cplusplus! hello cplusplus! 1 hello cplusplus! 1 1 总结: join 是让当前主线程等待所有的子线程执行完,才能退出。
detach如下:
#include<iostream> #include<thread> using namespace std; void show() { cout << "hello cplusplus!" << endl; } int main() { thread th(show); //th.join(); th.detach();//脱离主线程的绑定,主线程挂了,子线程不报错,子线程执行完自动退出。 //detach以后,子线程会成为孤儿线程,线程之间将无法通信。 cout << th.joinable() << endl; return 0; } 运行结果: hello cplusplus! 0 结论: 线程 detach 脱离主线程绑定,主线程退出,子线程不报错,子线程执行完自动退出。 线程 detach以后,子线程会成为孤儿线程,线程之间将无法通信或被同步。
|
|
| lambda与多线程 |
#include<iostream>
#include<thread> using namespace std; int main() { auto fun = [](const char *str) {cout << str << endl; }; thread t1(fun, "hello world!"); thread t2(fun, "hello beijing!"); return 0; }
|
|
| 线程交换 |
#include <iostream>
#include<thread>
using namespace std; int main() { thread t1([]() { cout << "thread1" << endl; }); thread t2([]() { cout << "thread2" << endl; }); cout << "thread1' id is " << t1.get_id() << endl; cout << "thread2' id is " << t2.get_id() << endl;
cout << "swap after:" << endl; swap(t1, t2);//线程交换 cout << "thread1' id is " << t1.get_id() << endl; cout << "thread2' id is " << t2.get_id() << endl; return 0; } 运行结果: thread1 thread2 thread1' id is 4836 thread2' id is 4724 swap after: thread1' id is 4724 thread2' id is 4836 两个线程通过 swap 进行交换。
|
|
| 线程移动 |
#include<iostream>
#include<thread> using namespace std; int main() { thread t1([]() { cout << "thread1" << endl; }); cout << "thread1' id is " << t1.get_id() << endl; thread t2 = move(t1);; cout << "thread2' id is " << t2.get_id() << endl; return 0; }
|
|
| 多线程可变参数 |
#include<iostream>
#include<thread> #include<cstdarg> using namespace std; int show(const char *fun, ...) { va_list ap;//指针 va_start(ap, fun);//开始 vprintf(fun, ap);//调用 va_end(ap); return 0; } int main() { thread t1(show, "%s %d %c %f", "hello world!", 100, 'A', 3.14159); return 0; } 运行结果: hello world! 100 A 3.14159</span>
|
|
| 线程类扩展 |
#include<iostream> #include<thread> using namespace std; class MyThread :public thread //继承thread { public: MyThread() : thread() { } //MyThread()初始化构造函数 template<typename T, typename...Args> MyThread(T&&func, Args&&...args) : thread(forward<T>(func), forward<Args>(args)...) { } void showcmd(const char *str) { system(str); //运行system } }; int main() { MyThread th1([]() { cout << "hello" << endl; }); th1.showcmd("calc"); //运行calc //lambda MyThread th2([](const char * str) { cout << "hello" << str << endl; }, " this is MyThread"); th2.showcmd("notepad");//运行notepad return 0; } 运行结果: hello //运行calc hello this is MyThread //运行notepad
|
|
|
this_thread
命名空间
|
thread的所有辅助函数位于std::this_thread命名空间中:
namespace this_thread
{
thread::id get_id() _NOEXCEPT;
inline void yield() _NOEXCEPT;
template<class_Rep, class_Period> inline
void sleep_for(const chrono::duration<_Rep,_Period>&_Rel_time)
template<class_Clock,class_Duration>inline
void sleep_until(const chrono::time_point<_Clock,_Duration>&_Abs_time)
}
|
|