我需要创建两个严格交替的线程。以下是我使用的示例代码:
#include <Windows.h>
#include <iostream>
using std::cout;
using std::endl;
HANDLE g_hMutex1;
HANDLE g_hMutex2;
DWORD WINAPI ThreadFunc1(LPVOID lpParam);
DWORD WINAPI ThreadFunc2(LPVOID lpParam);
int main(void)
{
int nCalcNumber = 10;
DWORD dwThreadId;
HANDLE pThreadHandles[2];
g_hMutex1 = CreateMutex(NULL, FALSE, NULL);
g_hMutex1 = CreateMutex(NULL, FALSE, NULL);
pThreadHandles[0] = CreateThread(
NULL,
0,
ThreadFunc1,
static_cast<void*>(&nCalcNumber),
0,
&dwThreadId);
pThreadHandles[1] = CreateThread(
NULL,
0,
ThreadFunc2,
static_cast<void*>(&nCalcNumber),
0,
&dwThreadId);
WaitForMultipleObjects(2, pThreadHandles, TRUE, INFINITE);
CloseHandle(pThreadHandles[0]);
CloseHandle(pThreadHandles[1]);
CloseHandle(g_hMutex1);
CloseHandle(g_hMutex2);
return 0;
}
DWORD WINAPI ThreadFunc1(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(g_hMutex1, INFINITE);
cout << "Func 1" << endl;
ReleaseMutex(g_hMutex1);
}
return 0;
}
DWORD WINAPI ThreadFunc2(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(g_hMutex1, INFINITE);
cout << "Func 2" << endl;
ReleaseMutex(g_hMutex1);
}
return 0;
}
结果,我希望收到:
Func 1
Func 2
Func 1
Func 2
Func 1
Func 2
...and so one
应该添加什么才能获得所需的结果。我可以使用第二个互斥锁吗?
答案 0 :(得分:7)
正如其他答案所述,信号量是一种比互斥锁更好的选择。但作为纯粹的学术练习(家庭作业?),你也可以使用互斥量。 (重点:这是一个纯粹的学术练习。一个真正的程序不应该使用这种技术。)
DWORD WINAPI ThreadFunc1(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
WaitForSingleObject(g_hMutex2, INFINITE);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(g_hMutex1, INFINITE);
ReleaseMutex(g_hMutex2);
cout << "Func 1" << endl;
ReleaseMutex(g_hMutex1);
WaitForSingleObject(g_hMutex2, INFINITE);
}
return 0;
}
DWORD WINAPI ThreadFunc2(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
WaitForSingleObject(g_hMutex2, INFINITE);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(g_hMutex1, INFINITE);
ReleaseMutex(g_hMutex2);
cout << "Func 2" << endl;
ReleaseMutex(g_hMutex1);
WaitForSingleObject(g_hMutex2, INFINITE);
}
return 0;
}
互斥锁1是“我拥有它”互斥锁,互斥锁2是“我想要它下一个”互斥锁。
答案 1 :(得分:3)
如果您可以使用semaphore
:您可以使用semaphore
代替mutex
,则可以轻松使用mutex
。
此代码可以正常工作:
#include <windows.h>
#include <iostream>
using std::cout;
using std::endl;
PHANDLE sem1;
PHANDLE sem2;
DWORD WINAPI ThreadFunc1(LPVOID lpParam);
DWORD WINAPI ThreadFunc2(LPVOID lpParam);
int main(void)
{
int nCalcNumber = 10;
DWORD dwThreadId;
HANDLE pThreadHandles[2];
sem1 = (PHANDLE) CreateSemaphore(NULL, 1, 1, NULL);
sem2 = (PHANDLE) CreateSemaphore(NULL, 0, 1, NULL);
pThreadHandles[0] = CreateThread(
NULL,
0,
ThreadFunc1,
static_cast<void*> (&nCalcNumber),
0,
&dwThreadId);
pThreadHandles[1] = CreateThread(
NULL,
0,
ThreadFunc2,
static_cast<void*> (&nCalcNumber),
0,
&dwThreadId);
WaitForMultipleObjects(2, pThreadHandles, TRUE, INFINITE);
CloseHandle(pThreadHandles[0]);
CloseHandle(pThreadHandles[1]);
CloseHandle(sem1);
CloseHandle(sem2);
return 0;
}
DWORD WINAPI ThreadFunc1(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*> (lpParam);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(sem1, INFINITE);
cout << "Func 1" << endl;
ReleaseSemaphore(sem2, 1 ,NULL);
}
return 0;
}
DWORD WINAPI ThreadFunc2(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*> (lpParam);
for (int i = 0; i < *nCalcNumber; i++)
{
WaitForSingleObject(sem2, INFINITE);
cout << "Func 2" << endl;
ReleaseSemaphore(sem1, 1 ,NULL);
}
return 0;
}
答案 2 :(得分:2)
你假设操作系统实际上支持这个。 Windows没有。它无法保证调度,除此之外没有饥饿。
所以你需要做的是设置一个标志变量,这样每个线程都会改变它以允许另一个线程运行。例如,如果它是真的 - 运行,如果它是假的 - 释放互斥锁并睡眠一段时间,而另一个线程 - 完全相反。睡眠在这里很重要,以避免饥饿和僵局。我认为它可以是Sleep(0)(检查它是否意味着Windows中的“产量”,我不确定)。
当然,检查应该在执行互斥锁时完成,并且在运行结束时,每个线程都会将变量更改为相反的 - 允许另一个线程运行并阻塞自己直到另一个线程运行然后改回来。
通过使变量成为计数器模数的线程数,并且每个线程在运行结束时增加值,并将模数值检查为线程的数字顺序,可以很容易地将其更改为2个以上的线程开头的执行。
修改强>
volatile bool flag = false;
DWORD WINAPI ThreadFunc1(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
for (int i = 0; i < *nCalcNumber; /*no-op*/;)
{
WaitForSingleObject(g_hMutex1, INFINITE);
if (flag) {Sleep(0); continue;}
cout << "Func 1" << endl;
flag = true;
i++;
ReleaseMutex(g_hMutex1);
}
return 0;
}
DWORD WINAPI ThreadFunc2(LPVOID lpParam)
{
int* nCalcNumber = static_cast<int*>(lpParam);
for (int i = 0; i < *nCalcNumber; /*no-op*/;)
{
WaitForSingleObject(g_hMutex1, INFINITE);
if (!flag) {Sleep(0); continue;}
cout << "Func 2" << endl;
flag = false;
i++;
ReleaseMutex(g_hMutex1);
}
return 0;
}