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