zoukankan      html  css  js  c++  java
  • 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();
    }
  • 相关阅读:
    sql注入式攻击的原理及实例分析 (转载)
    java中静态初始化块、初始化块和构造方法的理解 (转载)
    Java Web应用开发中的一些概念(转载)
    Map.Entry的使用(转载)
    java对象的存储位置(转载)-- 结合上一篇一起学习
    深入Java对象及元素的存储区域(转载)
    Java 面试题问与答:编译时与运行时(转载)看了一遍还不是很懂 先收着
    Liferay应用程序模板如何获取自定义结构的字段值
    FreeMarker 快速入门
    Tomcat9.x配置规范
  • 原文地址:https://www.cnblogs.com/si-lei/p/9508541.html
Copyright © 2011-2022 走看看