Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用互斥锁使两个线程严格交替?_C++_Multithreading_Winapi - Fatal编程技术网

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;
}