【问题标题】:WaitForSingleObject is not locking, Still allowing other threads to change value in C++WaitForSingleObject 未锁定,仍然允许其他线程在 C++ 中更改值
【发布时间】:2023-03-10 06:48:01
【问题描述】:

我正在尝试使用WaitForSingleObject(fork[leftFork], Infinite); 使用多个线程锁定一个变量,但它似乎没有锁定任何东西

我设置了Handle fork[5],然后使用下面的代码,但它似乎没有锁定任何东西。

while(forks[rightFork] == 0 || forks[leftFork] == 0) Sleep(0);
WaitForSingleObject(fork[leftFork], INFINITE);
forks[leftFork]--;

WaitForSingleObject(fork[rightFork], INFINITE);
forks[rightFork]--; 

我也尝试过WaitForMultipleObjects,结果相同。当我创建互斥体时,我使用fork[i]= CreateMutex(NULL, FALSE,NULL);

我想知道这是否只对每个线程都有好处,还是他们共享?

【问题讨论】:

  • 顺便说一句,您可能希望这样标记特定于 Windows 的内容。此外,要格式化代码,请选择它并按 CTRL+K。
  • 首先,检查WaitForSingleObject()WAIT_FAILED 的返回值。如果它们相等,请致电GetLastError() 并从那里继续。
  • 你怎么知道它没有锁定任何东西?预期/实际行为是什么?
  • 我重新格式化了您的代码和文本。照顾细节是值得的。 C++ 是区分大小写的,但你的字母大小写到处都是。线程很难,细节真的很重要。我没有将fork 数组重命名为spoons,但这很诱人!!
  • 您似乎正在用互斥量句柄填充 fork 数组,但随后通过递减句柄来跟进。这是不正确的——你对互斥体句柄所能做的就是等待它或释放它。

标签: c++ multithreading winapi locks


【解决方案1】:

首先,您没有提供足够的代码让我们能够帮助您确定正确性。但是,既然做了这个附带条件,我还是要试试!

您对 fork 一词的使用向我表明,您正在从 pthreads 背景接近 Windows 线程。 Windows 线程有点不同。令人困惑的是,Windows 中最有效的进程内互斥对象不是 mutex,它实际上是 临界区

critical section 的接口使用起来要简单得多,它本质上是一个获取函数和一个相应的释放函数。如果您在单个进程中进行同步,并且需要一个简单的锁(而不是信号量),那么您应该使用临界区而不是互斥锁。

事实上,就在昨天,我在 Stack Overflow 上写了一个 detailed answer 来回答一个描述关键部分的标准使用模式的问题。那篇文章有很多指向 MSDN 文档相关部分的链接。

话虽如此,看来您要做的只是同步整数值数组的递减。如果是这样,那么您可以通过InterlockIncrement 或其朋友之一以最简单的无锁方式执行此操作。

您只需要在执行跨进程同步时使用互斥锁。实际上,您应该只在跨进程同步时使用互斥锁,因为关键部分的性能要好得多(即更快)。由于您在这里更新一个简单的数组,并且由于没有明显可见的 IPC 正在进行,我只能得出结论,这确实是在进行中。

如果我错了,并且您确实在做跨进程工作并且需要互斥锁,那么我们需要查看更多代码。例如,我没有看到对ReleaseMutex 的任何调用。我不知道您是如何创建互斥锁的。

如果这没有帮助,请编辑您的问题以包含更多代码,以及您想要实现的目标的高级概述。

【讨论】:

  • 抱歉,我不确定如何附加文件,但我的代码如下。这是针对我的班级和全职工作的,老师只在白天有空,他不回复电子邮件,我的资源有限,但我们只允许在我们的解决方案中使用锁。我试过为单个对象和多个对象设置锁,但没有运气。我试图在不同的时间锁定阵列的每个部分,并且只有通过一次锁定整个阵列才能成功。
  • @tim 好的,关键部分是锁。您不能附加文件,但可以在问题中包含代码。真的,你为什么不使用临界区? InterlockedIncrement 会好得多,但是如果您正在学习有关锁的知识,那么它就是锁。但是从关键部分开始!!
  • 我会使用锁来创建临界区吗?首先我设置手柄 HANDLE fork[5]; for(int i = 0; i eatCount[left ])) 睡眠(0); { WaitForMultipleObjects(leftFork, fork, FALSE, INFINITE); // WaitForSingleObject(fork[leftFork], INFINITE);叉子[leftFork]--; WaitForMultipleObjects(rightFork, fork, FALSE, INFINITE); forks[rightFork]--;
  • @tim 不,关键部分对象是锁。它是 Windows 中的规范进程内锁。阅读我链接到的 Stack Overflow 答案以及答案所指的页面。我认为令人困惑的是 lock 和 mutex 是同义词,但 Windows Mutex 并不是您所设置任务的最佳锁。
  • @tim 你还没来得及阅读所有这些链接并消化它们。请尝试这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-20
  • 2020-04-27
  • 1970-01-01
  • 2020-07-29
  • 2022-01-16
  • 1970-01-01
相关资源
最近更新 更多