【发布时间】:2019-07-12 21:35:36
【问题描述】:
我正在尝试通过不同的方法将 CRITICAL_SECTION 的旋转计数设置为零:
int main()
{
CRITICAL_SECTION cs;
::InitializeCriticalSection(&cs);
printf("Spin count by default %08X\n", cs.SpinCount);
::DeleteCriticalSection(&cs);
::InitializeCriticalSectionAndSpinCount(&cs, 0);
printf("Spin count with zero spin count init %08X\n", cs.SpinCount );
::DeleteCriticalSection(&cs);
::InitializeCriticalSectionEx(&cs, 0, 0);
printf("Spin count with zero spin count and flags init %08X\n", cs.SpinCount );
::DeleteCriticalSection(&cs);
::InitializeCriticalSection(&cs);
::SetCriticalSectionSpinCount(&cs, 0);
printf("Spin count after explicit reset to zero %08X\n", cs.SpinCount);
::DeleteCriticalSection(&cs);
}
在 Windows 7 中,所有结果都如预期的那样为 0。
在 Windows 10 中,除了最后一个,所有结果都是 0x020007D0 值。最后一个结果是0x02000000。
显然,0x07D0 是实际的旋转计数(2000 十进制),0x02000000 是这些标志之一:
#define RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO 0x01000000
#define RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN 0x02000000
#define RTL_CRITICAL_SECTION_FLAG_STATIC_INIT 0x04000000
#define RTL_CRITICAL_SECTION_FLAG_RESOURCE_TYPE 0x08000000
#define RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO 0x10000000
我担心RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN 可能会导致临界区旋转,即使我使用SetCriticalSectionSpinCount 要求它不要旋转。
有没有办法不使用标准文档 API 来定义 RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN?
【问题讨论】:
-
听起来 API 可能会强制执行最小旋转计数。为什么你不希望它旋转?纺纱很好。
-
我知道特定的操作很慢,所以如果拥有关键部分,那么烧资源旋转没有意义,它不太可能很快免费,而是让给另一个线程会有所帮助这样资源可能会更快地释放出来。
-
它似乎没有完全强制执行最小值,因为将旋转计数设置为 1 确实将其设置为 1。调用
SetCriticalSectionSpinCount也可以 - 它可以将旋转计数设置为零。我唯一的问题显然是强制执行RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN标志。 -
如果您不想阻止,总有
TryEnterCriticalSection()。或者你可以使用互斥锁。请注意,RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN未记录在案;似乎没有任何关于它的实际用途的信息。 -
TryEnterCriticalSection不是一个选项,因为如果拥有对象,我想阻止。 WinAPI 互斥锁也不是一个选项,因为现在拥有对象时我不想进入内核。最接近的替代方案是 Slim Reader/Writer Lock,当被AcquireSRWLockExclusive/ReleaseSRWLockExclusive锁定时,它似乎完全符合我的需要,只是它没有递归支持。在 C++ 中,boost::mutex或std::mutex的 Visual Studio 实现也可以按照我的意愿行事(甚至还有这些的递归版本)。然而,我的问题是关于控制关键部分的行为。
标签: windows multithreading winapi critical-section