zoukankan      html  css  js  c++  java
  • 主线程和子线程多种情况小探讨

    一.背景

    今天看了一篇有关volatile在多线程中使用的博客(自己对该博客的总结:https://i-beta.cnblogs.com/posts/edit;postId=11388620),里面的例子没有详细地进行代码实现.自己想要验证下这个问题,同时练习下多线程编程的招式,去专门实现了一下.发现真正自己去动手时,头脑中会涌现出很多的疑问,同时也产生了很多的收获.

    二.代码示例

    代码要实现的功能是每隔一秒对flag_进行判断,如果flag_被另外的线程改为true的话,就会跳出循环.

    这里主要是针对主线程和子线程使用时,尝试了多种组合,看看都会有怎样的化学反应.

    #include <iostream>
    #include <windows.h>
    
    using namespace std;
    
    class Test
    {
    private:
        volatile bool m_bFlag;
    public:
        Test()
        {
            m_bFlag = false;
        }
        void Wait()
        {
            while (!m_bFlag)
            {
                cout << "I'm Sleeping" << endl;
                Sleep(1000);
            }
            cout << "I'm awake" << endl;
        }
    
        void WakeUp()
        {
            m_bFlag = true;
        }
    };
    
    DWORD WINAPI ThreadFun2(void *param)
    {
        Test *tThread = (Test *)param;
        tThread->WakeUp();
        return 0;
    }
    
    DWORD WINAPI ThreadFun1(void *param)
    {
        Test *tThread = (Test *)param;
        tThread->Wait();
        return 0;
    }
    
    /*下面实现一个线程隔1s进行等待判断,并且显式打印出"I'm Sleeping",另一个线程去把它的等待结束的过程.并标注下能否实现该需求.*/
    
    //这种情形会一闪而过,因为主线程没有等待子线程的过程,主线程结束后进程结束,子线程也终止了.
    //未能实现
    int main1()
    {
        Test t;
        //创建子线程
        HANDLE h = CreateThread(NULL, 0, ThreadFun1, &t, 0, NULL);
        t.WakeUp();
        return 0;
    }
    
    //会造成只执行子线程,主线程不执行的问题.这个时候我就误以为是主线程和子线程不能够同时运行了,其实这里是主线程使用让着子线程.
    //未能实现
    int main2()
    {
        Test t;
        //创建子线程
        HANDLE h = CreateThread(NULL, 0, ThreadFun1, &t, 0, NULL);
        WaitForSingleObject(h, INFINITE);    //INFINITE表示等待子线程结束后,才会走下面的逻辑.这里子线程的死循环无法打破,会一直阻塞在这里.
        t.WakeUp();                                                    
        return 0;
    }
    
    
    //这种情况能够保证子线程执行3s,然后把它WakeUp.
    //能实现
    int main3()
    {
        Test t;
        //创建子线程
        HANDLE h = CreateThread(NULL, 0, ThreadFun1, &t, 0, NULL);//主线程结束后,子线程也随之结束.
        Sleep(3000);//此处Sleep让你能看到子线程打印I'm Sleeping
    
        //调用过WakeUp后,要Sleep一会,不然主线程就直接结束了.
        t.WakeUp();
        Sleep(2000);
        return 0;
    }
    
    //这种只是来演示,主线程为死循环时,和子线程交替执行的情形.
    //不能实现
    int main4()
    {
        Test t;
        //创建子线程
        HANDLE h = CreateThread(NULL, 0, ThreadFun1, &t, 0, NULL);//如果是死循环,那么主线程不结束,子线程也不会结束.
        while (true)
        {
            Sleep(1000);
            cout << "主线程" << endl;
        }
    
        return 0;
    }
    
    
    //用两个子线程实现,发现两个子线程之间的生存期是相互独立的.它们只受主线程的影响.
    //可以实现.
    int main5()
    {
        Test t;
        HANDLE h[2];
        h[0] = CreateThread(NULL, 0, ThreadFun1, &t, 0, NULL);
        Sleep(10);//如果不加这个Sleep,多数情况下会先打印Sleeping,然后打印awake,但是也有情况会直接打印awake.
        h[1] = CreateThread(NULL, 0, ThreadFun2, &t, 0, NULL);
        WaitForMultipleObjects(2, h, TRUE, INFINITE);
        return 0;
    }

    三.收获

    1.主线程结束后进程结束,子线程也终止了.

    2.如果不设置主线程去等待子线程,两者是交替执行的.比如main4.

    3.两个子线程之间的生存期是相互独立的

    新战场:https://blog.csdn.net/Stephen___Qin
  • 相关阅读:
    匿名对象
    再次安装xampp遇到的各类问题汇总
    jupyter notebook添加Anaconda虚拟环境的python kernel
    1003. 我要通过!
    大数据分析-excel常用技巧
    Jupyter Notebook 修改默认打开的文件夹的位置
    A*算法介绍
    MATLAB常用函数(不定时更新)
    2019数学建模美赛感悟
    Windows许可证即将到期激活教程
  • 原文地址:https://www.cnblogs.com/Stephen-Qin/p/12708937.html
Copyright © 2011-2022 走看看