【问题标题】:Using events to synchronize threads使用事件同步线程
【发布时间】:2012-03-05 22:33:48
【问题描述】:

这是我第一次使用事件同步线程。我的代码工作正常。但根据我的经验,它看起来不错,但有明显的错误,当我在更大的项目中使用这个概念时,真的很难找到。

所以我只想问一下,这种使用事件来同步线程的方式是否适合你?

我们的想法是我们拥有只能从主线程调用的 GetSymbol 函数。服务器线程需要向主线程请求此函数的结果。

#include <windows.h>
#include <process.h>
#include <stdio.h>

HANDLE symbol_need, symbol_ready, end;

int symbol_container;

int GetSymbol()
{
    // Only main thread can use this function.
    static int i = 0;
    return ++i;
}

void Server(void* p)
{
    printf("Ask for first symbol.\n");
    SetEvent(symbol_need);

    DWORD wait_result;

    wait_result = WaitForSingleObject(symbol_ready, INFINITE);
    if(WAIT_OBJECT_0 == wait_result)
    {
        ResetEvent(symbol_ready);
        printf("First symbol: %i\n", symbol_container);
    } else {
        printf("Something went wrong.\n");
    }

    printf("Ask for second symbol.\n");
    SetEvent(symbol_need);

    wait_result = WaitForSingleObject(symbol_ready, INFINITE);
    if(WAIT_OBJECT_0 == wait_result)
    {
        ResetEvent(symbol_ready);
        printf("Second symbol: %i\n", symbol_container);
    } else {
        printf("Something went wrong.\n");
    }

    printf("OK, finish it.");
    SetEvent(end);
}


int main(int argc, char* argv[])
{
    symbol_need = CreateEvent( NULL, FALSE, FALSE, NULL );
    symbol_ready = CreateEvent( NULL, FALSE, FALSE, NULL );
    end = CreateEvent( NULL, FALSE, FALSE, NULL );

    _beginthread(Server, 0, NULL);

    DWORD wait_result;

    while(1)
    {
        wait_result = WaitForSingleObject(symbol_need, 100);
        if(WAIT_OBJECT_0 == wait_result)
        {
            ResetEvent(symbol_need);
            symbol_container = GetSymbol();
            SetEvent(symbol_ready);
        }
        wait_result = WaitForSingleObject(end, 100);
        if(WAIT_OBJECT_0 == wait_result)
        {
            break;
        }
    }
    return 0;
} 

【问题讨论】:

  • 代码有一种难闻的味道。对ResetEvent 的调用充其量是多余的(因为您正在使用自动重置事件),最坏的情况可能会导致事件丢失,从而导致死锁。只需删除它们。
  • @arx 实际上,由于主线程无法在Server 线程发出其事件信号之前为下一次迭代执行SetEvent,因此Server 线程不可能意外重置自己的事件。但我同意他应该切换到手动事件或删除重置。

标签: c++ c multithreading winapi


【解决方案1】:

是的,这段代码是正确的。

这个例子有助于了解事件是如何工作的。但是,当您编写生产代码时,无需重新发明轮子。例如,您描述的交互可以使用英特尔 TBB 库中的并发数据结构进行优雅建模,例如concurrent_bounded_queue.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-30
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    • 1970-01-01
    相关资源
    最近更新 更多