我想围绕复杂的多线程代码编写一些断言。 有没有办法做一个
assert(GetCurrentThreadId() == ThreadOfCriticalSection(sec));
答案 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)
您的要求没有意义。如果您当前的线程不是临界区中的线程,那么当前线程中的代码将不会运行,在尝试锁定临界区时它将被阻止。
如果你的线程实际上在临界区内,那么你的断言将永远是真的。如果不是,你的断言将永远是假的!
所以我的意思是,假设你能够跟踪关键部分中的哪个线程,如果你将断言置于关键部分代码中,它将永远是真的。如果你把它放在外面,它总是错误的。