【问题标题】:Critical Sections and return values in C++C++ 中的临界区和返回值
【发布时间】:2012-07-25 15:20:11
【问题描述】:

在尝试从头开始创建线程安全的容器类时,我遇到了从访问方法返回值的问题。例如在 Windows 中:

myNode getSomeData( )
{
  EnterCriticalSection(& myCritSec);
  myNode retobj;
  // fill retobj with data from structure
  LeaveCriticalSection(& myCritSec);
  return retobj;
}

现在我认为这种类型的方法根本不是线程安全的,因为在代码释放临界区之后,另一个线程能够出现并在第一个线程返回之前立即覆盖retobj。那么以线程安全的方式将retobj 返回给调用者的优雅方式是什么?

【问题讨论】:

  • 但是retobj是存储在栈上的吗?除非它被声明为“静态”,否则复制的数据被覆盖应该没有问题。
  • 除非发生奇怪的事情,retobj 应该在堆栈上,并且每个线程都应该有自己的堆栈。当您使用预先分配的内存并且必须锁定访问以防止共享时,这种竞争条件更为常见。
  • @inface,好点,所以只要返回值存储在堆栈上我就很好。

标签: c++ multithreading winapi return-value critical-section


【解决方案1】:

不,它是线程安全的,因为每个线程都有自己的堆栈,这就是retobj 所在的位置。

但是,它肯定不是异常安全的。将关键部分包装在 RAII 样式的对象中会有所帮助。比如……

class CriticalLock : boost::noncopyable {
  CriticalSection &section;

public:
  CriticalLock(CriticalSection &cs) : section(cs)
  {
    EnterCriticalSection(section);
  }

  ~CriticalLock()
  {
    LeaveCriticalSection(section);
  }
};

用法:

myNode getSomeData( )
{
  CriticalLock  lock(myCritSec);  // automatically released.
  ...
} 

【讨论】:

    【解决方案2】:

    这是C++,retobj有自动存储类型,所以是在栈上存储的。

    每个线程都有自己的堆栈,因此另一个线程在返回之前无法破坏retobj 的值。

    【讨论】:

      猜你喜欢
      • 2020-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-21
      相关资源
      最近更新 更多