我正在尝试通过不同的方法将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
吗?
答案 0 :(得分:0)
偷看实施后,自己想办法。
当InitializeCriticalSectionEx
与非零旋转计数一起使用时,RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN
标志未设置。因此,这段代码输出00000001
:
::InitializeCriticalSectionEx(&cs, 1, 0);
printf("Spin count after explicit one %08X\n", cs.SpinCount);
::DeleteCriticalSection(&cs);
一个旋转计数几乎为零。而且,随后调用SetCriticalSectionSpinCount
可以将其重置为零。因此,这段代码输出00000000
:
::InitializeCriticalSectionEx(&cs, 1, 0);
::SetCriticalSectionSpinCount(&cs, 0);
printf("Spin count after explicit one and then reset to zero %08X\n", cs.SpinCount);
::DeleteCriticalSection(&cs);
当然,应该有充分的理由禁止旋转。默认情况下,正如@JonathanPotter指出的那样,旋转是好的。否则,它不会被设置为默认行为。因此,我什至没有将禁用旋转的解决方案应用于我原来的问题。
另一方面,关键部分的维护者可能无意不尊重传递给InitializeCriticalSectionEx
或InitializeCriticalSectionAndSpinCount
的零旋转计数。他们只是确保普通InitializeCriticalSection
获得自动旋转计数。