使用Visual c ++进行多线程同步不起作用

时间:2018-03-15 01:29:43

标签: c++ multithreading winapi visual-c++

我正在使用Visual c ++学习多线程程序来开发声音信号处理程序。为了创建程序的基本结构,我编写了一个简单的代码,它有四个同步移动的线程,但它们不能正常工作。 规格如下。

  1. 有四个线程:bg_thread,main_thread,sub_thread [0],sub_thread [1]。
  2. bg_thread定期触发main_thread
  3. main_thread每次触发sub_thread [0]并每两次触发一次sub_thread [1]。
  4. main_thread是main_class
  5. 中的一个函数
  6. sub_thread [0],sub_thread [1]是sub_class
  7. 中的函数

    该计划如下:

    #include "process.h"
    #include "windows.h"
    #include "stdio.h"
    
    class Sub_class
    {
    public:
        HANDLE hEvent2;
        Sub_class(int no);
        bool loop_ok;
        bool calcstart;
        int sub_class_no;
    
        void do_sub_loop2();
    };
    
    class Main_class {
    public:
        bool thread_go;
        bool go_flag = false;
        Sub_class *sub_cls[2];
    
        Main_class();
        ~Main_class();
        int start_loop();
    };
    
    Main_class *main_cls = 0;
    HANDLE g_bg_wait = 0;
    HANDLE g_main_event = 0;
    bool bg_go = true;
    
    unsigned __stdcall start_bg_loop(void *parg)
    {
        WaitForSingleObject(g_bg_wait, INFINITE);
    
        while (bg_go)
        {
            Sleep(100); // goto sleep for 100 milliseconds
            SetEvent(g_main_event);
        }
        return 0;
    }
    
    unsigned __stdcall start_main_loop(void *parg)
    {
        main_cls->start_loop();
        return 0;
    }
    //---------------------------------------------------------------------------------
    int main()
    {
        main_cls = new Main_class();
    
        HANDLE hEvent = 0;
        HANDLE hndl = 0;
    
        hEvent = CreateEvent(NULL, TRUE, FALSE, "bg_event");
        hndl = (HANDLE)_beginthreadex(0, 0, &start_bg_loop, 0, 0, 0);
        g_bg_wait = hEvent;
    
        hEvent = CreateEvent(NULL, FALSE, FALSE, "main_event");
        hndl = (HANDLE)_beginthreadex(0, 0, &start_main_loop, 0, 0, 0);
        g_main_event = hEvent;
    
        main_cls->sub_cls[0] = new Sub_class(0);
        main_cls->sub_cls[1] = new Sub_class(1);
    
        Sleep(1000);
    
        bg_go = false;
        CloseHandle(g_bg_wait);
        CloseHandle(g_main_event);
    }
    
    
    int Main_class::start_loop()
    {
        Sleep(10);
        SetEvent(g_bg_wait);
    
        while (thread_go)
        {
            WaitForSingleObject(g_main_event, INFINITE);
    
            printf("Trigger SubClass 0\n");
            sub_cls[0]->calcstart = true;
            SetEvent(sub_cls[0]->hEvent2);
    
            if (go_flag)
            {
                printf("Trigger SubClass 1\n");
                sub_cls[1]->calcstart = true;
                SetEvent(sub_cls[1]->hEvent2);
            }
            else
            {
                sub_cls[1]->calcstart = false;
            }
            go_flag = !go_flag;
        }
        return 0;
    }
    
    Main_class::Main_class()
    {
        thread_go = true;
    }
    
    Main_class::~Main_class()
    {
        thread_go = false;
    }
    
    static unsigned __stdcall executeLauncher2(void* args) {
        reinterpret_cast<Sub_class*>(args)->do_sub_loop2();
        return 0;
    }
    Sub_class::Sub_class(int no)
    {
        sub_class_no = no;
        loop_ok = true;
        hEvent2 = CreateEvent(0, FALSE, FALSE, "event_2");
        _beginthreadex(0, 0, &executeLauncher2, (void *)this, 0, 0);
    }
    void Sub_class::do_sub_loop2()
    {
        while (loop_ok)
        {
            WaitForSingleObject(hEvent2, INFINITE);
            if (calcstart) printf("Start SubClass %d : OK\n", sub_class_no);
            else printf("Start SubClass %d : NG ---\n", sub_class_no);
        }
    }
    

    运行该程序的结果如下:

    Trigger SubClass 0
    Start SubClass 0 : OK
    Trigger SubClass 0
    Trigger SubClass 1
    Start SubClass 1 : NG ---
    Start SubClass 0 : OK
    Trigger SubClass 0
    Start SubClass 1 : NG ---
    Trigger SubClass 0
    Trigger SubClass 1
    Start SubClass 0 : OK
    Start SubClass 1 : OK
    Trigger SubClass 0
    Start SubClass 0 : OK
    Trigger SubClass 0
    Trigger SubClass 1
    Start SubClass 1 : NG ---
    Start SubClass 0 : OK
    Trigger SubClass 0
    Start SubClass 1 : NG ---
    Trigger SubClass 0
    Trigger SubClass 1
    Start SubClass 1 : OK
    Start SubClass 0 : OK
    Trigger SubClass 0
    Start SubClass 1 : NG ---
    

    从结果中可以看出,即使触发sub_thread [0],也经常调用sub_thread [1](NG行)。 我想创建程序,以便在触发sub_thread [0]时调用sub_thread [0]并在触发sub_thread [1]时, 调用sub_thread [1],也就是说,我想阻止NG行。

    你能教我如何解决这个问题吗? 提前谢谢。

1 个答案:

答案 0 :(得分:5)

  

CreateEvent(0, FALSE, FALSE, "event_2");

在此创建或打开相同的事件,因为您将名称传递给该函数。甚至程序的多个实例也会打开相同的事件对象。如果任何其他程序创建了一个具有通用名称“event_2”的事件,您也可以打开它。那肯定不是你想要的。

传递NULL作为最后一个参数,为每个线程创建不同的事件对象。命名事件通常仅用于跨进程同步(在这种情况下,使用唯一的名称,如GUID),这里不需要。