简体   繁体   中英

Multi-thread syncronizing using Visual c++ do not work

I'm studying multi-thread program using Visual c++ to develop a sound signal processing program. To create basic structure of the program, I wrote a simple code having four threads that move synchronously, but they do not work well. Specifications are as follows.

  1. There are four threads: bg_thread, main_thread, sub_thread [0], sub_thread [1].
  2. bg_thread triggers main_thread at regular intervals
  3. main_thread triggers sub_thread [0] every time and triggers sub_thread [1] once every two times.
  4. main_thread is a function in main_class
  5. sub_thread [0], sub_thread [1] are functions in sub_class

The program is as follows:


#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);
    }
}

The result of running this program is as follows:


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 ---

As you can see from the result, sub_thread [1] is often invoked (line of NG) even though triggering sub_thread [0]. I want to create the program so that when sub_thread [0] is triggered, sub_thread [0] is invoked and when sub_thread [1] is triggered, sub_thread [1] is invoked, that is, I want to prevent NG lines.

Could you teach me how to fix this program, please ? Thank you in advance.

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

Here you create or open the same event, because you pass a name to the function. Even multiple instances of your program would open the same event object. If any other program had created an event with such a generic name as "event_2", you would also open that. That's certainly not what you want.

Pass NULL for the last parameter to create distinct event objects for each thread. Named events are usually only used for cross-process synchronization (in which case one uses unique names like a GUID), which you don't need here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM