C++ 如何使用互斥锁使两个线程严格交替?
我需要创建两个严格交替的线程。下面是我使用的示例代码:C++ 如何使用互斥锁使两个线程严格交替?,c++,multithreading,winapi,C++,Multithreading,Winapi,我需要创建两个严格交替的线程。下面是我使用的示例代码: #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(voi
#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;
}
应该添加什么以获得所需的结果。我可以使用第二个互斥锁吗?您假设操作系统实际上支持这一点。Windows没有。除了没有饥饿外,它对日程安排没有任何保证 因此,您需要做的是设置一个标志变量,以便每个线程都将更改它以允许另一个线程运行。例如,如果它是true-运行,如果它是false-释放互斥并休眠一段时间,而另一个线程-正好相反。睡眠对于避免饥饿和僵局很重要。我想它可能是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;
}
volatile bool标志=false;
DWORD WINAPI ThreadFunc1(LPVOID lpParam)
{
int*nCalcNumber=静态_转换(lpParam);
对于(int i=0;i<*nCalcNumber;/*无操作*/;)
{
WaitForSingleObject(g_hMutex1,无穷大);
if(flag){Sleep(0);continue;}
cout如果您可以使用信号量
:您可以使用信号量
而不是互斥
,它与互斥
一样易于使用
此代码工作正常:
#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;
}
#包括
#包括
使用std::cout;
使用std::endl;
幻影sem1;
幻影sem2;
DWORD WINAPI ThreadFunc1(LPVOID lpParam);
DWORD WINAPI ThreadFunc2(LPVOID lpParam);
内部主(空)
{
int nCalcNumber=10;
德沃德·德维德;
句柄pthreadholds[2];
sem1=(幻影)CreateSemaphore(NULL,1,1,NULL);
sem2=(幻影)CreateSemaphore(NULL,0,1,NULL);
pthreadholds[0]=CreateThread(
无效的
0,
第1条,
静态铸件(NCALCU编号),
0,
&dwid);
pthreadholds[1]=创建线程(
无效的
0,
第2条,
静态铸件(NCALCU编号),
0,
&dwid);
WaitForMultipleObjects(2,pThreadHandles,TRUE,无限);
CloseHandle(pThreadHandles[0]);
CloseHandle(pThreadHandles[1]);
闭合手柄(sem1);
闭合手柄(sem2);
返回0;
}
DWORD WINAPI ThreadFunc1(LPVOID lpParam)
{
int*nCalcNumber=静态_转换(lpParam);
对于(int i=0;i<*nCalcNumber;i++)
{
WaitForSingleObject(sem1,无限);
cout如其他答案所述,信号量比互斥量好得多。但作为纯学术练习(家庭作业?),你也可以用互斥量来做。(强调:这是纯学术练习。真正的程序不应该使用这种技术。)
DWORD WINAPI ThreadFunc1(LPVOID lpParam)
{
int*nCalcNumber=静态_转换(lpParam);
WaitForSingleObject(g_hMutex2,无穷大);
对于(int i=0;i<*nCalcNumber;i++)
{
WaitForSingleObject(g_hMutex1,无穷大);
释放互斥(g_hmutex 2);
你现在的结果是什么?为什么你要这样做,因为这会破坏多线程的全部用途。这是家庭作业吗?我想说你根本不需要线程…你声明两个互斥句柄,1和2,然后在1处创建两个互斥体,所以泄漏一个互斥体。然后两个线程获取/释放相同的互斥体1。我同意与@DanielMošmondor一起使用e。如果您需要严格的替换,为什么不使用光纤(如果您确实需要两个不同的堆栈)这是我的下一个阶段。我的工作通常是用C语言来做的。现在我想学习C++。谢谢,这个代码真的很有用。我意识到信号灯的优势。但是有可能解决这个问题吗?只用互斥吗?@泰纳尔:我想是下注。在解决方案中,可能有一种使用互斥体的解决方案。这里不需要创建一个命名的信号量。事实上,这是一个错误,因为如果您运行两个程序副本,它们将共享同一对信号量,而不是各自拥有自己的私有信号量。@RaymondChen:是的,但这不是在实际环境中运行的程序,它只是一个s足够显示信号量的用法来解决问题。虽然,他可以通过替换NULL来发出名称,这个问题将得到解决。我更新了答案。谢谢你的答案。我想象你的决定如下:WaitForSingleObject,而我检查全局变量的循环,cout to stream,change global variable,ReleaseMutex。所以我可以n只使用一个互斥体。有没有没有没有while循环的解决方案?@tenere,while
循环与互斥体无关,而是如何管理线程。在代码中,你有一个与之完全相同的for
循环,因此你不需要任何额外的循环,只要在线程启动时增加for
循环计数器即可lly运行,而Sleep则不然。@Tenere-您的原始代码就快到了。两个互斥体本来可以工作,但您在同一个句柄上创建了两个互斥体。如果创建1和2,线程A可以释放互斥体2并等待互斥体1。线程B可以释放互斥体1并等待互斥体2。实际上,您是在两个线程之间交换令牌
#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;
}
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;
}