簡體   English   中英

使用Visual c ++的多線程同步不起作用

[英]Multi-thread syncronizing using Visual c++ do not work

我正在研究使用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. sub_thread [0],sub_thread [1]是sub_class中的函數

該程序如下:


#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行。

請您教我如何修復該程序? 先感謝您。

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

在這里,您創建或打開相同的事件,因為您將名稱傳遞給該函數。 甚至程序的多個實例也會打開同一事件對象。 如果其他任何程序創建了一個通用名稱為“ event_2”的事件,您也將打開它。 那當然不是你想要的。

為最后一個參數傳遞NULL ,以為每個線程創建不同的事件對象。 命名事件通常僅用於跨進程同步(在這種情況下,該事件使用唯一的名稱,如GUID),在此不需要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM