从不同的线程打印Hello和World

时间:2012-09-12 14:30:39

标签: multithreading visual-c++

我创建了一个多线程程序。这里一个线程打印“Hello”,另一个打印“World”,输出将是“Hello World”50次。它运行正常,但它使用的是事件,它是内核对象,需要在用户模式和内核之间切换。任何人都可以在VC ++中建议任何更轻的版本而不是C#或java。

  #include <Windows.h>


static HANDLE event1 = CreateEvent(NULL, TRUE, TRUE, NULL); 
static HANDLE event2 = CreateEvent(NULL, TRUE, TRUE, NULL); 


DWORD WINAPI ThreadHello(  __in  LPVOID lpParameter)
{
    for( int i = 0 ; i < 50 ; i++ )
    {
        WaitForSingleObject(event1, INFINITE);
        ResetEvent(event1);
        printf("%s ", "Hello");
        SetEvent(event2);
    }

    return 1;
}

DWORD WINAPI ThreadWorld(  __in  LPVOID lpParameter)
{
    for( int i = 0 ; i < 50 ; i++)
    {
        WaitForSingleObject(event2, INFINITE);
        ResetEvent(event2);
        printf("%s\n", "World");
        SetEvent(event1);
    }

    return 1;
}


int _tmain(int argc, _TCHAR* argv[])
{
    CreateThread(NULL, 0, ThreadHello, (LPVOID)0, 0, 0);
    CreateThread(NULL, 0, ThreadWorld, (LPVOID)0, 0, 0);

    getchar();

    return 0;
}

4 个答案:

答案 0 :(得分:2)

为什么要尝试在多个线程中执行此操作?现在你的线程以锁步方式执行,这意味着它们中只有一个一次运行。在这种情况下,我会重新设计使用单个线程。

如果你这样做是为了代码清晰而不是并发执行(一种罕见的情况,但仍然可能),请考虑使用fibers。代码结构与线程几乎相同,但不是设置和等待事件,而是通过调用SwitchToFiber来抢占当前光纤以运行另一个光纤。

您应该使用多线程的主要情况是:

  1. 当您遇到可以分成多个部分的CPU限制问题时 - 您的打印过程可能受CPU限制,但不能分成多个部分。您的文件读取问题可能不受CPU限制。
  2. 处理不支持异步调用的库时,需要在后台运行。
  3. 因为它使您的代码更简单而且您不关心开销 - 例如在服务器应用程序中为每个线程处理一个请求时

答案 1 :(得分:1)

尝试原子比较和交换,在那里忙着等待尝试获取锁定。它很粗糙,因为它忙着等待,但它会给你一些有用技术的经验。

答案 2 :(得分:1)

我理解这个问题是通用的。也可以使用Critical Section Objects来解决这种情况。

DWORD WINAPI ThreadHello(  __in  LPVOID lpParameter)
{
  for( int i = 0 ; i < 50 ; i++ )
  {
    EnterCriticalSection(&csMyCriticalSectionObject);
    printf("%s ", "Hello");
    LeaveCriticalSection(&csMyCriticalSectionObject);
    // now we're ending the threads quantum
    Sleep(0);
    // ThreadWord is waiting on EnterCriticalSection, thus ready to execute and
    // therefore executed next.
  }
  return 1;
}

DWORD WINAPI ThreadWorld(  __in  LPVOID lpParameter)
{
  for( int i = 0 ; i < 50 ; i++)
  {
    EnterCriticalSection(&csMyCriticalSectionObject);
    printf("%s\n", "World");
    LeaveCriticalSection(&csMyCriticalSectionObject);
    // now we're ending the threads quantum
    Sleep(0);
    // ThreadHello is waiting on EnterCriticalSection, thus ready to execute and
    // therefore executed next.
  }
  return 1;
}


// global
CRITICAL_SECTION csMyCriticalSectionObject;


int _tmain(int argc, _TCHAR* argv[])
{
  // initialize the critical section object
  InitializeCriticalSection(&csMyCriticalSectionObject);

  CreateThread(NULL, 0, ThreadHello, (LPVOID)0, 0, 0);
  CreateThread(NULL, 0, ThreadWorld, (LPVOID)0, 0, 0);

  getchar();

  return 0;
}

当您的需求是多线程缓冲输出时,您应该考虑排队机制,例如同步的fifo。所有输出都可以通过任意个线程排队到该队列。单个输出线程可以出列到输出(printf)。

答案 3 :(得分:0)

问题域太模糊和抽象,实际上并不适合作为正确的多线程编程。我知道你正处于学习阶段,但你必须要真实。您应该采取一些用户输入,读取一些文件,等待一些外部事件(如时间/时间,文件更改,用户登录,下载完成等),在线程(读取器线程,编写器线程)和类似的东西之间正确同步。

对于您遇到的问题,您可能想要使用Critical Sections或Reader-Writer Locks。