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