在函数和子函数中调用相同的临界区

问题描述 投票:1回答:1

我是一名支持工程师,在失败过程的转储中,我看到有一些锁。

使用Windbg(Visual Studio无法正确处理调用堆栈)我发现一个函数(ClassName::F())正在回来。该函数使用一个关键部分,并调用一个子函数(ClassName::f_sub()),简而言之,他正在调用相同的关键部分:

int ClassName::f_sub(){
  EnterCriticalSection(&m_cs);
  ...
  LeaveCriticalSection(&m_cs);
  return ...;
}

int ClassName::F() {
  EnterCriticalSection(&m_cs);
  ...
  int temp = f_sub();
  ...
  LeaveCriticalSection(&m_cs);
  return ...;
}

每次使用相同的关键部分m_csClassName的财产)。

在我看来,这使得以下顺序成为可能:

Thread 1 : F()     : Enter the critical section. (Thread 1 is in)
Thread 1 : f_sub() : Enter the critical section. (Thread 1 is in)
Thread 1 : f_sub() : Leave the critical section. (Thread 1 is out)
Thread 2 : F()     : Enter the critical section. (Thread 2 is in) 

=> WRONG! Thread 2 should be forced to wait for Thread 1 leaving the critical section via F().

我的分析是否正确,这是否意味着建议对主要和子功能使用不同的关键部分?

c++ multithreading critical-section
1个回答
1
投票

我的分析是否正确,这是否意味着建议对主要和子功能使用不同的关键部分?

来自Microsoft Docs(强调我的):

在线程拥有关键部分的所有权后,它可以对EnterCriticalSection或TryEnterCriticalSection进行额外调用,而不会阻止其执行。这可以防止线程在等待它已经拥有的关键部分时自行死锁。每次EnterCriticalSection和TryEnterCriticalSection成功时,线程都会进入临界区。每次进入临界区时,线程必须调用一次LeaveCriticalSection。

所以不,你所描述的不应该发生。完全可以多次进入临界区,并且需要完全保留多次。

© www.soinside.com 2019 - 2024. All rights reserved.