wordpress做个人博客,合肥seo培训,天津市建设工程评标专家网,网站建设征求意见分析报告目录case1#xff1a;创建线程1 join、detachcase2#xff1a;创建线程2 线程传参 传值或者传引用case3#xff1a;创建线程 线程传参 functional object作为参数case4#xff1a;观察多线程程序加速计算case5#xff1a;future get 获取并发结果case6#xff1a;互斥锁… 目录case1创建线程1 join、detachcase2创建线程2 线程传参 传值或者传引用case3创建线程 线程传参 functional object作为参数case4观察多线程程序加速计算case5future get 获取并发结果case6互斥锁case7std::lock_guard 类模板 case1创建线程1 join、detach
创建线程并等该线程执行完毕,并且打印两个线程的id
#include iostream
#include thread
using namespace std;
void func() {cout hello , this is my thread, thread id is this_thread::get_id() endl;
}
int main() {thread th thread(func);th.join();cout this is main thread and its id is this_thread::get_id() endl;
}执行结果如下
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe
hello , this is my thread, thread id is 2
this is main thread and its id is 1Process finished with exit code 0使用detach放弃对该线程的控制
#include iostream
#include threadusing namespace std;void func() {cout hello , this is my thread, thread id is this_thread::get_id() endl;
}
int main() {thread th thread(func);th.detach();// 如果我们此时不再关系该线程的运行情况的话可以使用detachcout th.joinable() endl;cout this is main thread and its id is this_thread::get_id() endl;
}运行结果
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe
0
this is main thread and its id is 1
hello , this is my thread, thread id is 2Process finished with exit code 0case2创建线程2 线程传参 传值或者传引用
传值
#include iostream
#include threadusing namespace std;void func(string s) {cout hello , this is my thread, thread arg is s endl;
}
int main() {thread th thread(func, test);th.join();cout this is main thread and its id is this_thread::get_id() endl;
}打印结果如下
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe
hello , this is my thread, thread arg is test
this is main thread and its id is 1Process finished with exit code 0传引用
#include iostream
#include threadusing namespace std;void func(string s) {cout (s) endl;cout hello , this is my thread, thread arg is s endl;
}
int main() {string str test;thread th thread(func, ref(str));cout (str) endl;th.join();cout this is main thread and its id is this_thread::get_id() endl;
}打印结果如下
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe
0x62fd10
0x62fd10
hello , this is my thread, thread arg is test
this is main thread and its id is 1Process finished with exit code 0case3创建线程 线程传参 functional object作为参数
关于仿函数的定义可以看仿函数 如果单纯地将逻辑函数传入thread在函数逻辑比较复杂的时候不太好。 将函数封装到类的内部可以赋予一定的封装性并且可以在类内部创建例如map的数据结构来记录函数运行的状态。 仿函数、不带参
#include iostream
#include threadusing namespace std;// functional object
struct A {void operator()() {cout Im A endl;}
};
void show() {cout Im show endl;
}
int main() {show();A a;a(); // 等价于 a.operator()();// 我们把这种object称为callable的object 又称为仿函数thread thread1 thread(A());thread1.join();return 0;
}打印结果如下
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe
Im show
Im A
Im AProcess finished with exit code 0仿函数、带参
#include iostream
#include threadusing namespace std;// functional object
struct A {void operator()(int num) {for (int i 0; i num; i) {cout Im A i endl;}}
};int main() {int num 10;thread thread1 thread(A(), num);for (int i 0; i num; i) {cout Im main i endl;}thread1.join();return 0;
}打印结果如下是乱序的符合多线程特性 并且 cout 并不是线程安全的所以可以发现有乱码的样子
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe
Im mainIm A00Im A1
Im A2
Im A3
Im AIm main41Im mainIm A25Im mainIm A36Im AIm main47Im main5
Im mainIm A86Im mainIm A97Im main8
Im main9Process finished with exit code 0lambda函数作为参数
#include iostream
#include threadusing namespace std;int main() {string s test;thread f thread([s](int a,int b) {cout s endl;cout a b endl;}, 2, 3);f.join();return 0;
}打印结果
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe
test
5Process finished with exit code 0case4观察多线程程序加速计算
#include iostream
#include threadusing namespace std;// 测量一个函数的运行时间
template class T
void measure(T func) {using namespace std::chrono;auto start system_clock::now();// funcfunc();durationdouble diff system_clock::now() - start;cout 执行了 diff.count() 秒 endl;
}// 求和函数[start,end)
void sum(long start, long end, long ans) {long s 0;for(auto i start; i end; i) {s i;}ans s;
}const long S 100000000;int main() {// 测量一下把工作分摊给两个线程做的时间measure([](){long ans1, ans2;thread t1 thread(sum, 0, S 1, std::ref(ans1));thread t2 thread(sum, S 1, S, std::ref(ans2));t1.join();t2.join();cout ans ans1 ans2 endl;});// 测量一下单线程工作时间measure([](){long ans;sum(0, S, ans);cout ans ans endl;});return 0;
}打印结果
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe
ans 887459712
执行了0.13546秒
ans 887459712
执行了0.240006秒Process finished with exit code 0当然这里有一个细节 如果在多线程程序中我们传入了一个ref引用在线程程序中我们最好不要直接对这个ref值操作而是采用一个临时变量例如上面的程序中我们就使用了一个临时变量s对s进行累加后再把值赋给ans。这样会提高程序运行效率。
case5future get 获取并发结果
future包裹线程运行结果使用方法如下 由于我们线程函数的结果是long所以首先定义futurelong
#include iostream
#include thread
#include future
#include vectorusing namespace std;// 测量一个函数的运行时间
template class T
void measure(T func) {using namespace std::chrono;auto start system_clock::now();// funcfunc();durationdouble diff system_clock::now() - start;cout 执行了 diff.count() 秒 endl;
}// 求和函数[start,end)
long sum(long start, long end) {long s 0;for(auto i start; i end; i) {s i;}return s;
}const long S 100000000;int main() {// 测量一下把工作分摊给 threadNums 个线程做的时间measure([](){const long threadNums 8;vectorfuturelong vec;vec.reserve(threadNums);for (int i 0; i threadNums; i) {vec.push_back(async(sum, (S / threadNums) * i, (S / threadNums) * (i 1)));}long ans 0;// get 阻塞式地拿到并发结果for (int i 0; i threadNums; i) {ans vec[i].get();}cout ans ans endl;});// 测量一下单线程工作时间measure([](){long ans sum(0, S);cout ans ans endl;});return 0;
}运行结果如下
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe
ans 887459712
执行了0.0521455秒
ans 887459712
执行了0.250044秒Process finished with exit code 0case6互斥锁
多个线程访问同一个值并且对其修改会导致数据竞争。
#include iostream
#include thread
#include future
#include vectorusing namespace std;
// 测量一个函数的运行时间
template class T
void measure(T func) {using namespace std::chrono;auto start system_clock::now();// funcfunc();durationdouble diff system_clock::now() - start;cout 执行了 diff.count() 秒 endl;
}std::mutex mtx;
// 求和函数 线程安全的
void sum(long s) {mtx.lock();for (int i 0; i 100000; i) {s;}mtx.unlock();
}int main() {// 测量一下把工作分摊给 threadNums 个线程做的时间measure([](){vectorthread v;long s 0;for (int i 0; i 4; i) {v.emplace_back(std::thread(sum, std::ref(s)));}for (int i 0; i 4; i) {v[i].join();}cout ans s endl;});measure([](){long s 0;for (int i 0; i 4; i) {sum(s);}cout ans s endl;});return 0;
}测试结果
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe
ans 400000
执行了0.0141654秒
ans 400000
执行了0.0155926秒Process finished with exit code 0case7std::lock_guard 类模板
如果mtx.lock()和mtx.unlock()之间的语句发生了异常unlock()语句没有机会执行 这会导致mtx一直处于锁着的状态其他使用sum函数的线程就会阻塞。 c库已经提供了std::lock_guard类模板构造时自动加锁析构时自动解锁 将case6的sum函数修改为下面形式即可
// 求和函数 线程安全的
void sum(long s) {std:;lock_guardstd::mutex guard(mtx);// mtx.lock();for (int i 0; i 100000; i) {s;}// mtx.unlock();
}如果想自己实现的lock_guard的话也可以
class mutexLockGuard{
private:std::mutex mtx;
public:explicit mutexLockGuard(std::mutex mutex) : mtx(mutex){mtx.lock();}~mutexLockGuard() {mtx.unlock();}
};笔记参考 C多线程快速入门