1

我正在用 C++ 编写一个单例 Logger 类。此类为多个线程提供日志记录 API。为了使其线程安全,我使用了 wxCRIT_SECT_LOCKER宏。

假设我在我的 Logger 类中有以下功能(简单示例):

void Logger::error( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);

  // do something such as getting/setting class members 
  m_err_cnt++;

  do_log("Error: " + msg);
}

void Logger::warning( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);

  // do something such as getting/setting class members 
  m_warn_cnt++;

  do_log("Warning: " + msg);
}

void Logger::do_log( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);

  // do something such as getting/setting class members 
  m_log_cnt++;


  cout << msg << endl;
}

问题:

Logger::warning()被调用时,我们将进入临界区两次,一次在Logger::warning()中,另一次在 *Logger::do_log()* 中。

如果您同意问题是真实存在的并且可能导致死锁,我该如何避免多个锁(使用 wxCriticalSection 类/宏)。

4

1 回答 1

1

通常所做的是创建不带锁的内部 API,这些 API 由带锁的公共 API 调用。

void Logger::error( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);
  m_err_cnt++;
  do_log_internal("Error: " + msg);
}

void Logger::warning( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);
  m_warn_cnt++;
  do_log_internal("Warning: " + msg);
}

void Logger::do_log( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);
  do_log_internal(msg);
}

void Logger::do_log_internal( string msg )
{
  m_log_cnt++;
  cout << msg << endl;
}

但是,对于您的问题,您可能宁愿直接使用,并在构造时wxMutex使用类型。wxMUTEX_RECURSIVE这样,互斥体就有了计数。当互斥锁第一次被锁定时,计数设置为 1。如果同一个线程再次抓取互斥锁,它会增加一个计数。释放互斥锁会减少计数。当计数达到 0 时,互斥锁被解锁。

于 2013-08-20T07:41:28.073 回答