多线程中的singleton用法

singleton usage in multithread

本文关键字:用法 singleton 多线程      更新时间:2023-10-16

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

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

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

我对以上文本的问题是

  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();之前被调用。在这种情况下,对象将已被删除,指针将无效。

作者所说的糟糕的代码设计意味着糟糕的类和方法构造;在哪里放置什么以及该位置如何使代码可访问。

"如果一个对象必须在线程范围之外持久存在,那么它应该由另一个不会超出范围的线程创建和拥有。"

简单地说,上面的意思是,如果你在A(线程)中有B,但你需要在C中也使用B,那么你必须从线程(A)中删除B,并使其独立于它,这样你就可以在A和C中都使用它

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

关于引用的文本:如果你用得不对。如果两个线程正在访问相同的线程例如,则ref应该已经至少为2,因此如果一个线程删除引用,对象仍将继续存在。不需要任何额外的线程使事情复杂化。