C++多线程编程一
1.C++多线程初步:
#include <iostream> #include <thread> #include <Windows.h> using namespace std; void run() { MessageBoxA(0, "hello world", "hello china", 0); } void main0101() { //同步(阻塞) run(); run(); run(); cin.get(); } void main0102() { //并行,异步,非阻塞 thread t1(run); //根据函数初始化并执行,t1在栈上 thread t2(run); thread t3(run); thread t4(run); cin.get(); } void main0103() { //并行,异步,非阻塞 //thread t[5]{ run,run,run,run,run }; //error C2440: “初始化”: 无法从“void (__cdecl *)(void)”转换为“std::thread” thread t[5]{ thread(run),thread(run), thread(run), thread(run), thread(run) }; //初始化线程数组(线程池) cin.get(); } void main0104() { //堆上 thread *pthread1(new thread(run)); thread *pthread2(new thread(run)); thread *pthread3(new thread(run)); cin.get(); } void main() { //堆上开辟了线程数组 thread *pthread1(new thread[5]{ thread(run),thread(run), thread(run), thread(run), thread(run) }); cin.get(); }
2. 线程冻结与解冻调试:
#include <iostream> #include <thread> #include <Windows.h> #include <cstdlib> using namespace std; void test() { int i = 0; while (1) { cout << ++i << endl; Sleep(1000); } } void main() { thread *p(new thread(test)); //堆上 system("pause"); system("pause"); system("pause"); system("pause"); cin.get(); }
3. 多线程传参:
#include <iostream> #include <thread> #include <Windows.h> using namespace std; void showmsg(const char *str1, const char *str2) { MessageBoxA(0, str1, str2, 0); } void main() { thread th1(showmsg, "1", "1"); thread th2(showmsg, "111", "111"); thread th3(showmsg, "222", "222"); cin.get(); }
4. 多线程的join 和detach:
#include <iostream> #include <thread> #include <array> #include <Windows.h> using namespace std; //join让当前主线程等待所有子线程执行完成才能退出 //detach脱离主线程的绑定,主线程退出的时候,不影响子线程。 void show() { MessageBoxA(0, "1", "1", 0); } void main0401() { 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(); //主线程等待子线程执行完成再退出 } auto n = thread::hardware_concurrency(); //获取CPU是几核 cout << n << endl; cin.get(); } void main() { thread th(show); //th.join(); th.detach(); //脱离主线程,主线程挂了不报错 //detach以后线程无法通信 th.joinable(); }
5. 原子变量与线程安全:
#include <iostream> #include <thread> #include <mutex> //互斥量 #include <atomic> //原子变量 using namespace std; //线程安全,多线程访问不冲突就是线程安全,冲突则不安全 //int num = 0; //mutex m; //互斥,加锁解锁浪费时间 atomic_int num(0); //原子变量不会发生线程冲突,属于线程安全 void run() { for (int i = 0; i < 10000000; i++) { //m.lock(); num++; //m.unlock(); } } void main() { clock_t start = clock(); thread th1(run); thread th2(run); th1.join(); th2.join(); clock_t end = clock(); cout << num << endl; cout << end - start << "ms" << endl; cin.get(); } //全局变量,会发生冲突,结果不正确,速度快 //mutex,结果正确,速度慢 //atomic,结果正确,速度比mutex快
6. lambda 表达式与多线程:
#include <iostream> #include <thread> #include <Windows.h> #include <chrono> using namespace std; void main0701() { //auto fun = []() {MessageBoxA(0, "1", "2", 0); }; //thread th1(fun); //thread th2(fun); thread th1([]() {MessageBoxA(0, "11", "22", 0); }); thread th2([]() {MessageBoxA(0, "11", "22", 0); }); cin.get(); } void main() { //thread th1([]() {cout << this_thread::get_id() << endl; }); //获取当前线程的id //thread th2([]() {cout << this_thread::get_id() << endl; }); thread th1([]() { this_thread::sleep_for(chrono::seconds(3)); //等待3秒 this_thread::yield(); //让CPU先执行其他线程,空闲了再执行我 cout << this_thread::get_id() << endl; //获取当前线程的id //this_thread::sleep_until(); //某个时刻到来之前一直等待 }); thread th2([]() { this_thread::sleep_for(chrono::seconds(10)); //等待10秒 cout << this_thread::get_id() << endl; }); cin.get(); }
7. 伪函数与多线程:
(1)伪函数概念:
#include <iostream> using namespace std; struct func { void operator ()() //伪函数,可以将对象名当做函数名来使用 { cout << "hello china hello cpp" << endl; } void operator ()(int i) //伪函数,可以将对象名当做函数名来使用 { cout << "hello china hello cpp! " << i << endl; } }; void main() { func f1; f1(); func f2; f2(2); cin.get(); }
(2)伪函数与多线程:
#include <iostream> #include <thread> #include <Windows.h> using namespace std; struct MyStruct { MyStruct() { cout << "create" << endl; } ~MyStruct() { cout << "end" << endl; } void operator ()() //对象名当做函数名使用,重载了(),但()只适用于当前结构体对象 { MessageBoxA(0, "111", "222", 0); } }; void main() { MyStruct go1; thread t1(go1); MyStruct go2; thread t2(go2); //MyStruct()是构造函数,创建一个临时对象,匿名对象 //MyStruct()(); //thread t3(MyStruct());//匿名的对象,不适合作为多线程参数,销毁太快 //MyStruct *p = new MyStruct; MyStruct *p = new MyStruct();//多一个()就是构造函数 cin.get(); }
8. 成员函数构建多线程:
#include <iostream> #include <thread> #include <Windows.h> using namespace std; struct fun { void run1() { MessageBoxA(0, "12345", "ABCDE", 0); cout << "hello china" << endl; } void run2(const char *str) { MessageBoxA(0, str, str, 0); cout << "hello china" << endl; } }; void main() { //fun *p(nullptr); //p->run1(); //空类指针可以引用没有调用内部变量的成员函数 fun fun1; //&fun::run引用成员函数 thread th1(&fun::run1, fun1); thread th2(&fun::run1, fun1); thread th3(&fun::run2, fun1,"run2-1"); thread th4(&fun::run2, fun1, "run2-2"); cin.get(); }
9. 多线程通信future:
#include <iostream> #include <thread> #include <future> #include <string> #include <cstdlib> using namespace std; void main0401() { string str1("12345"); string str2("678910"); string str3(str1 + str2); //C++风格的字符串 cout << str3 << endl; cin.get(); } promise<string>val; //全局通信变量 void main() { thread th1([]() { future<string> fu = val.get_future();//获取未来的状态 cout << "等待中..." << endl; cout << fu.get() << endl; }); thread th2([]() { system("pause"); val.set_value("I love CPP"); system("pause"); }); th1.join(); th2.join(); }
10. 基于继承的多线程:
#include <iostream> #include <thread> using namespace std; class zhangthread :public thread //C++代码重用-->继承 { public: zhangthread() :thread() //子类调父类的构造函数 { } template <typename T, typename...Args> //子类调父类的构造函数,可变参数的构造 zhangthread(T && func,Args &&...args):thread( forward<T>(func), forward<Args>(args)... ) { } void run(const char *cmd) //新增的功能 { system(cmd); } }; void main() { zhangthread t1([](){cout << "hello this is Zhang"<<endl;}); t1.run("calc"); zhangthread t2([](int num) {cout << "hello this is Zhang"<<num<<endl; },100 ); t2.run("notepad"); cin.get(); }
11. 条件变量:
#include <iostream> #include <thread> #include <mutex> #include <condition_variable> //条件变量 using namespace std; //线程通信,结合mutex //一个线程,多个线程处于等待,通知一个或通知多个 mutex m; //线程互相排斥 condition_variable cv; //线程通信 void main() { thread **th = new thread * [10];//开辟线程的指针数组 for (int i = 0; i < 10; i++) { th[i] = new thread([](int index) { unique_lock<mutex> lck(m); //锁定 cv.wait_for(lck, chrono::hours(1000)); //一直等待 cout << index << endl; //打印编号 } , i ); //传递参数 this_thread::sleep_for(chrono::milliseconds(100)); //错开 } for (int i = 0; i < 10; i++) { lock_guard<mutex> lckg(m);//解锁向导 cv.notify_one(); //挨个通知 } for (int i = 0; i < 10; i++) { th[i]->join(); delete th[i]; } delete[]th; //释放指针数组 cin.get(); }
12. 获取线程的结果:
#include <iostream> #include <thread> #include <future>//线程将来结果 #include <chrono>//时间 #include <mutex> using namespace std; mutex g_m; void main() { auto run = [=](int index)->int { lock_guard<mutex> lckg(g_m); //加锁 cout << this_thread::get_id() << " " << index << endl; //获取线程id this_thread::sleep_for(chrono::seconds(10)); //等待10秒 return index * 1024; //返回结果 }; packaged_task<int(int)> pt1(run); packaged_task<int(int)> pt2(run); //创建两个任务包 thread t1([&]() {pt1(2); }); thread t2([&]() {pt2(3); }); //开启线程 cout << pt1.get_future().get() << endl; cout << pt2.get_future().get() << endl; //获取结果 t1.join(); t2.join(); cin.get(); }
13. 可变参数实现多线程:
#include <iostream> #include <cstdarg> #include <thread> using namespace std; //可变参数 int go(const char *fmt, ...) { va_list ap; //第一个数据(指针) va_start(ap, fmt); //开始 vprintf(fmt, ap); //调用 va_end(ap); //结束 return 0; } void main() { thread th(go, "%sABCD%d____%c____%x", "12345abc", 123, 'A', 256); cin.get(); }
14. 多线程实现并行计算:
#include <iostream> #include <thread> #include <future> #include <vector> #include <cstdlib> using namespace std; #define COUNT 1000000 //线程函数: int add(vector<int> *arr, int start, int count) { static mutex m; //静态局部变量,只会初始化一次 int sum(0);//保存结果 for (int i = 0; i < count; i++) { sum += (*arr)[start + i];//实现累加 } { //此处仅仅是计算过程中的显示,更清楚查看 lock_guard<mutex> lckg(m);//加锁,不让其他线程干涉 cout << "thread" << this_thread::get_id() << ",count=" << count << ",sum=" << sum << endl; } return sum; } void main() { vector<int> data(COUNT); //数组,100万的大小 for (int i = 0; i < COUNT; i++) { data[i] = i % 1000; //0-999 } vector< future<int> > result;//结果数组 int cpus = thread::hardware_concurrency();//CPU核心的个数 for (int i = 0; i < cpus * 2; i++) { //1000 10= 100 * 10 //1000 9 = 1000 - 111*8 int batch_each = COUNT / (cpus * 2); if (i == (cpus * 2) - 1) { batch_each = COUNT - COUNT / (cpus * 2)*i;//最后一个承担的多一点 } //不断压入结果 result.push_back(async(add, &data, i*batch_each, batch_each));//async直接返回结果 } //汇总 int lastresult(0); for (int i = 0; i < cpus * 2; i++) { lastresult += result[i].get();//汇总结果,累加 } cout << "lastresule=" << lastresult << endl; cin.get(); }
文章写来不易,转载请标注。。。欢迎关注!