我可以获得持有CriticalSection的线程的id吗?

时间:2010-11-27 01:56:41

标签: multithreading winapi critical-section

我想围绕复杂的多线程代码编写一些断言。 有没有办法做一个

assert(GetCurrentThreadId() == ThreadOfCriticalSection(sec));

3 个答案:

答案 0 :(得分:4)

如果你想正确地做到这一点,我认为你在关键部分周围使用了一个包装器对象,它将跟踪调试版本中每个CS拥有哪个线程(如果有的话)。

即。您不必直接调用EnterCriticalSection,而是在您的包装器上调用一个方法来执行EnterCriticalSection,然后在成功时将GetCurrentThreadId存储在断言将检查的DWORD中。另一种方法是在调用LeaveCriticalSection之前将该线程ID DWORD归零。

(在发布版本中,包装器可能会省略额外的东西,只需调用Enter / LeaveCriticalSection。)

正如卡萨布兰卡指出的那样,所有者线程ID在当前的CRITICAL_SECTION结构中,因此使用我建议的包装器将存储冗余信息。但是,正如卡萨布兰卡所指出的那样,CRITICAL_SECTION结构不是任何API合同的一部分,可能会发生变化。 (实际上,在以前的Windows版本中已经更改了。)

了解内部结构对于调试很有用,但不应在生产代码中使用。

您使用哪种方法取决于您希望解决方案的“正确”程度。如果您只想在当前版本的Windows上使用一些临时断言来跟踪问题,那么直接使用CRITICAL_SECTION字段对我来说似乎是合理的。只是不要指望这些断言永远有效。如果你想要的东西会持续更长时间,请使用包装器。

(使用包装器的另一个好处是你会获得RAII。即包装器的构造函数和析构函数将处理InitializeCriticalSection和DeleteCriticalSection调用,因此你不必再担心它们了。说到这个,我发现它非常有用的是有一个辅助对象,它在构造中进入CS然后自动离开它。没有更多的关键部分意外地被锁定,因为一个函数在它的中间隐藏了一个早期的返回......)

答案 1 :(得分:1)

据我所知,没有记录的方法来获取这些信息。如果查看标题,CRITICAL_SECTION结构包含一个线程句柄,但我不会依赖这些信息,因为内部结构可能会更改,恕不另行通知。更好的方法是在线程进入/退出关键部分时自己维护此信息。

答案 2 :(得分:0)

您的要求没有意义。如果您当前的线程不是临界区中的线程,那么当前线程中的代码将不会运行,在尝试锁定临界区时它将被阻止。

如果你的线程实际上在临界区内,那么你的断言将永远是真的。如果不是,你的断言将永远是假的!

所以我的意思是,假设你能够跟踪关键部分中的哪个线程,如果你将断言置于关键部分代码中,它将永远是真的。如果你把它放在外面,它总是错误的。