0

我正在阅读一本关于应用 C++ 的关于锁定和设计的书。

void addRef() { ref++; }
void subRef() { if(--ref == 0) delete this; }

尽管像 ref++ 这样的语句看起来微不足道,但不能保证它是原子的。但在您重写此代码以添加锁定之前,您需要知道您的应用程序将如何使用它。在这个特定的示例中,如果在 subRef 之后调用 addRef,则会创建一个错误。问题不在于缺少锁,而是设计不佳。如果一个对象必须在线程范围之外持续存在,则它应该由不会超出范围的不同线程创建和拥有。

我对上述文字的问题是

  1. 作者所说的糟糕设计是什么意思,以及如何通过“如果一个对象必须在线程范围之外持续存在,它应该由不会超出范围的不同线程创建和拥有”来避免这种情况。? 请求对此举个例子。
4

3 回答 3

1
void thread1work(RefCntObj* refcntObj) 
{
  refcntObj.addRef();
  // any work
  refcntObj.subRef();
}

int main(void) {
  RefCntObj* refcntObj= new RefCntObj(); // I assume the constructor calls addRef()
  std::thread t(thread1work, std::ref(f));
  refcntObj->subRef(); // may be called after thread1Work or before it
}

不能保证thread1work将在 main 之前调用refcntObj->subRef();。在这种情况下,对象已经被删除并且指针无效。

于 2013-07-30T08:44:39.860 回答
0

作者说的代码设计不佳,是指类和方法的构造不佳;您在哪里放置什么以及该位置如何使您的代码可访问。

“如果一个对象必须在线程范围之外持续存在,它应该由不会超出范围的不同线程创建和拥有。”

简单地说,上面的意思是如果你在 A(Thread) 内部有 B 但你需要在 C 中也使用 B,那么你必须从 thread(A) 内部删除 B 并使其独立于它,所以你可以使用它在 A 和 C 中。

于 2013-07-30T08:42:35.927 回答
0

谁知道?你得问问作者。对我来说,这看起来像是经典的引用计数:为了确保安全,您必须使用互斥锁来保护对 的所有访问ref,或者制作 ref某种原子变量。(C++11 有一系列std::atomic<int>你可以使用的函数。)

关于引用的文字:如果你没有正确使用它,你可以使任何东西变得不安全。如果两个线程正在访问同一个实例,则ref应该已经至少为 2,这样如果一个线程丢弃了引用,该对象仍将继续存在。不需要任何额外的线程来使事情复杂化。

于 2013-07-30T08:46:54.667 回答