并发与并行

网上看到一组生动形象描述并发与并行的图片:

并发

同时间只能处理一种操作

【C++】【多线程】

并行

同一时间可以处理多种操作

【C++】【多线程】

C++11多线程

每个C++程序均包含默认主线程main函数,通过thread创建新线程,可为thread对象附加回调,回调类型支持函数指针、函数对象、Lambda。

Hello World !

单线程

#include <iostream>

using namespace std;

int main()
{
    cout<<"Hello World !"<<endl;

    return 0;
}

多线程

#include <iostream>
#include <thread>

using namespace std;

void sayHi()
{
    cout<<"Hello World !"<<endl;
}

int main()
{
    thread* t = new thread(sayHi);
    t->join();
    delete t;

    return 0;
}
#include <iostream>
#include <thread>

using namespace std;

struct MyStruct
{
    void sayHi()
    {
        cout<<"Hello World !"<<endl;
    }
}

int main()
{
    MyStruct s;
    thread* t = new thread(&MyStruct::sayHi, s);
    t->join();
    delete t;

    return 0;
}

敲黑板——知识点

join():调用者将等待目标线程结束后继续运行。

detach():调用者与目标线程分离,调用者无需等待目标线程结束。

线程对象可移动不可复制

#include <iostream>
#include <thread>

using namespace std;

void f1();
void f2();

int main()
{
    thread t1(f1);
    //thread t2 = t1;        //编译错误
    thread t2 = move(t1);    //此时t1中没有线程
    t1 = thread(f2);
    thread t3 = move(t2);    //此时t2中没有线程
    //t1 = move(t3);         //程序终止,因为t1中已有线程在管理

    return 0;
}

互斥锁

无互斥锁时:打印输出看心情,因为cout是共享资源~

#include <iostream>
#include <thread>

using namespace std;

void f1() {
    for(int i = 0; i < 100; i++)
        cout << i << endl;
}

int main()
{
    thread t1(f1);

    for(int i = 0; i > -100; i--)
        cout << i << endl;

    t1.join();

    return 0;
}

有互斥锁时:

#include <iostream>
#include <thread>
#include <mutex>

using namespace std;

mutex mu;

void test(int i) {
    mu.lock();
    cout << i << endl;
    mu.unlock();
}

void f1() {
    for(int i = 0; i < 100; i++)
        test(i);
}

int main()
{
    thread t1(f1);

    for(int i = 0; i > -100; i--)
        test(i);

    t1.join();

    return 0;
}

BUT 如果lock()和unlock()之间发生异常,unlock()没机会执行时,会导致互斥锁一直处于锁住状态,会导致线程阻塞。

为解决此问题,引入RAII(Resource Acquisition Is Initialization 获取资源即初始化)技术。在类的构造函数中创建资源,析构函数中释放资源,这样即使发生异常,也能保证析构函数的执行。

#include <iostream>
#include <thread>
#include <mutex>

using namespace std;

mutex mu;

void test(int i) {
    lock_guard<mutex> guard(mu);
    cout << i << endl;
}

void f1() {
    for(int i = 0; i < 100; i++)
        test(i);
}

int main()
{
    thread t1(f1);

    for(int i = 0; i > -100; i--)
        test(i);

    t1.join();

    return 0;
}

封装互斥锁保护数据

#include <iostream>
#include <thread>
#include <mutex>
#include <fstream>

using namespace std;

mutex mu;

class LogFile {

    mutex m_mutex;
    ofstream f;

    public:
        LogFile() 
        {
            f.open("log.txt");
        }

        ~LogFile() 
        {
            f.close();
        }

        void test(int id) 
        {
            std::lock_guard<std::mutex> guard(mu);
            f << id << endl;
        }

        /*
        // Never ever ever!!!不要返回数据,提供泄露数据的机会
        ofstream& getStream()
        {
            return f;
        }
        */

        /*
        // Never ever ever!!!不要传递数据,提供泄露数据的机会
        void process(void fun(ostream&))
        {
            fun(f);
        }
        */
};

void f1(LogFile& log) {
    for(int i = 0; i < 100; i++)
        log.test(i);
}

int main()
{
    LogFile log;
    
    thread t1(f1, ref(log));

    for(int i = 0; i > -100; i--)
        log.test(i);

    t1.join();

    return 0;
}

参考文档:https://segmentfault.com/a/1190000016171072

相关文章:

  • 2021-10-26
  • 2022-02-28
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-12
  • 2021-04-14
  • 2021-04-11
相关资源
相似解决方案