C++多线程编程学习笔记
来源:互联网 发布:macbookair怎样装软件 编辑:程序博客网 时间:2024/06/11 03:28
头文件:#include<thread>创建线程 void show(int x){ cout<<"hello,world"<<x<<endl; thread t1(show,1);}另一种构造方式class Factor{ void operator()(string s){ cout<< s <<endl; }};int main(){ thread t1(Factor(),"123456"); /*或者 Factor f; thread t1(f,"123456"); */ return 0;}引用传递class Factor{ void operator()(string &s){ cout<< s <<endl; }};int main(){ string str = "I want to Success!"; thread t1(Factor(),ref(str)); return 0;}启动线程t1.join();t1.detach();//这种方式将会使主进程不管子进程是否执行完。//以上两种方法只能运行其中一个线程只能被移动不能被赋值string happy = "I want to Success";thread t1((show()),ref(happy));thread t2 = move(t1);//❌ thread t2 = t1; 不能被赋值//t1.join();❌ t1已经为空,不可再开始t2.join();获取进程id string happy = "I want to Success"; cout<<"Main Thread id : "<<this_thread::get_id()<<endl; thread t1((show()),ref(happy)); cout<<"T1 Thread id : "<<t1.get_id()<<endl; thread t2 = move(t1); cout<<"T2 Thread id : "<<t2.get_id()<<endl; t2.join();/*结果:Main Thread id : 0x7fff75f5a300T1 Thread id : 0x100381000T2 Thread id : 0x100381000I want to Success*/显示最多可以多少个线程并发编程cout<<thread::hardware_concurrency()<<endl;解决资源竞争看下面这段代码#include <iostream>#include <thread>#include <string>#include <mutex>using namespace std;mutex mu;class show{public: void operator()(string msg){ for (int i=0; i<10; ++i) { cout<<msg<<" "<<i<<endl; } }};int main(){ string msg = "I want to Success"; thread t1(show(),msg); for (int i=0; i>-10; --i) { cout<<msg<<" "<<i<<endl; } t1.join(); return 0;}/* 运行结果: I want to Success 0I Iw awnatn tt ot oS uScuccecsess s0 -1I wIa nwta ntto tSou cScuecscse ss1 -2I wIa nwta ntto tSou cScuesscces s2 -3I wIa nwta ntto tSou cScuecscse s3s -I4 waIn tw atnot Stuoc cSeuscsc e4ss I- 5wanIt wtaon tS utcoc eSsusc c5essI -w6antI twoa nStu ctcoe sSsu c6cesIs w-a7nt It ow aSnutc cteos sS u7cceIs sw a-n8t tIo wSaunctc etsos S8uccIe swsa n-t9 to Success 9*/出现杂乱无章的原因是主线程与t1线程同步运行,两个线程同时竞争cout。解决方法,使用mutex互斥访问临界资源#include <mutex>mutex mu;然后在cout使用之前加锁,使用后解锁mu.lock();cout<<msg<<" "<<i<<endl;mu.unlock();解决后运行结果I want to Success 0I want to Success -1I want to Success 0I want to Success -2I want to Success 1I want to Success -3I want to Success 2I want to Success -4I want to Success 3I want to Success -5I want to Success 4I want to Success -6I want to Success 5I want to Success -7I want to Success 6I want to Success -8I want to Success 7I want to Success -9I want to Success 8I want to Success 9但lock方法存在一定的风险,即cout出现异常时,cout将会被永远锁定所以我们用 lock_guard<mutex> guard(mu);当guard析构时,无论是否掏出异常,mu将会被自动解锁。但是cout是一个全局变量,可能别的线程仍可以访问它,所以我们需要资源绑定绑定方法为自己实现一个ofstream 类对象 将执行结果输出在文件中。#include <iostream>#include <thread>#include <string>#include <mutex>#include <fstream>using namespace std;class logFile{ ofstream f; mutex m_mutex;public: logFile(){ f.open("/Users/shizheng/Desktop/log.txt"); } void print(string str,int i){ lock_guard<mutex> guard(m_mutex); f<<str<<":"<<i<<endl; }};class show{public: void operator()(string msg,logFile &log){ for (int i=0; i<10; ++i) { log.print(msg, i); } }};int main(){ logFile log; thread t1(show(),"T1 thread",ref(log)); for (int i=0; i>-10; --i) { log.print("Main thread", i); } t1.join(); return 0;}只要不将f泄露,就不会引起资源竞争。死锁,与解决死锁的办法先写一个出现死锁的小例子#include <iostream>#include <thread>#include <string>#include <mutex>#include <fstream>using namespace std;mutex mu;class logFile{ ofstream f; mutex m_mutex1,m_mutex2;public: logFile(){ f.open("/Users/shizheng/Desktop/log.txt"); } void print(string str,int i){ lock_guard<mutex> guard1(m_mutex1); lock_guard<mutex> guard2(m_mutex2); cout<<str<<":"<<i<<endl; } void print2(string str,int i){ lock_guard<mutex> guard2(m_mutex2); lock_guard<mutex> guard1(m_mutex1); cout<<str<<":"<<i<<endl; }};class show{public: void operator()(string msg,logFile &log){ for (int i=0; i<100; ++i) { log.print(msg, i); } }};int main(){ logFile log; thread t1(show(),"T1 thread",ref(log)); for (int i=0; i>-100; --i) { log.print2("Main thread", i); } t1.join(); return 0;}以上出现死锁的原因是因为print将mutex1锁住而print2需要mutex1,print2需要mutex2而此时mutex2被print锁住。解决办法void print(string str,int i){ lock(m_mutex1,m_mutex2); lock_guard<mutex> guard1(m_mutex1,adopt_lock); lock_guard<mutex> guard2(m_mutex2,adopt_lock); cout<<str<<":"<<i<<endl; } void print2(string str,int i){ lock(m_mutex1,m_mutex2); lock_guard<mutex> guard2(m_mutex2,adopt_lock); lock_guard<mutex> guard1(m_mutex1,adopt_lock); cout<<str<<":"<<i<<endl; }//lock(m_mutex1,m_mutex2); AND同步机制,要可以分配一起分配,释放时一起释放//lock_guard<mutex> guard1(m_mutex1,adopt_lock);//adopt_lock的作用是告诉guard1 只需要获取mutex的所有权,无需加锁 unique_lock<mutex> locker(m_mutex1,defer_lock); //..... m_mutex1.lock(); cout<<str<<":"<<i<<endl; m_mutex1.unlock(); //........ unique_lock<mutex> locker2 = move(locker);//unique_lock 可以局部加锁,比lock_guard有弹性,但是比lock_guard更多的消耗性能。defer_lock 表示,m_mutex1并没有被锁住once_flag m_flag;call_once(m_flag,[&](){f.open("log.txt");});//以上代码保证文件只被打开一次。多线程的条件变量以下代码为模拟生产者消费者模式,使用条件变量使消费者进程在等待生长过程中的多次循环,用条件变量在无产品时,自动休眠。#include<iostream>#include <mutex>#include <queue>#include <thread>#include <condition_variable>using namespace std;queue<int> q;mutex mu;condition_variable cond;void fun1(){ int count =10; while (count>0) { unique_lock<mutex> locker(mu); q.push(count); mu.unlock(); cond.notify_one();//一但生产则唤醒休眠的消费者程序。notify_one为唤醒一个,notify_all为唤醒多个。 printf("生产者:%d\n",count); this_thread::sleep_for(chrono::seconds(1)); count--; }}void fun2(){ int data = 0,count=0; while (data!=1) { unique_lock<mutex> locker(mu); cond.wait(locker,[](){return !q.empty();});//先解锁休眠进程,等待唤醒,唤醒后再加锁 //这里cond可能被自己激活,称为伪激活,第二个参数为lamda函数,队列不为空才会被激活 data = q.front(); q.pop(); mu.unlock(); printf("消费者:%d\n",data); count++; printf("消费者循环等待次数:%d\n",count); } }int main(){ thread t1(fun1); thread t2(fun2); t1.join(); t2.join(); return 0;}
0 0
- 多线程编程学习笔记
- Linux centOS c语言 多线程编程学习笔记
- C# 多线程编程学习笔记
- Posix多线程编程学习笔记
- Java 多线程编程 学习笔记
- Posix多线程编程学习笔记
- Posix多线程编程学习笔记
- Posix多线程编程学习笔记
- Posix多线程编程学习笔记
- 多线程编程学习笔记-interlocked
- C++多线程编程学习笔记
- Posix多线程编程学习笔记
- Linux多线程编程--学习笔记--多线程简介
- block 知识点 ---- Objective-C 高级编程 iOS 与 OS X 多线程内存管理 学习笔记
- c#.net 多线程编程学习(1)
- c#.net 多线程编程学习(2)
- c#.net 多线程编程学习(3)
- Linux C 多线程编程学习(二)
- 文件操作
- 使用intellij idea搭建MAVEN+springmvc+mybatis框架
- python(八)socket网络编程
- 图像识别中的深度学习
- java 多数据源实例
- C++多线程编程学习笔记
- 类加载器CLASSLOADER的工作机制
- linux or mac 简单定制命令(svn 批量处理命令)
- CSS实现头尾高度固定,中部内容百分百填充
- 菲常记忆专题
- 学习SQLite之路(一)
- 数字图像处理的基本原理和常用方法
- java.lang.RuntimeException: Unable to instantiate application com.android.tools.fd.runtime.Bootstrap
- 10.7