我创建了一个多线程程序。这里一个线程打印“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;
}
答案 0 :(得分:2)
为什么要尝试在多个线程中执行此操作?现在你的线程以锁步方式执行,这意味着它们中只有一个一次运行。在这种情况下,我会重新设计使用单个线程。
如果你这样做是为了代码清晰而不是并发执行(一种罕见的情况,但仍然可能),请考虑使用fibers。代码结构与线程几乎相同,但不是设置和等待事件,而是通过调用SwitchToFiber来抢占当前光纤以运行另一个光纤。
您应该使用多线程的主要情况是:
答案 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。