C++ 比较一些原子交换

C++ 比较一些原子交换,c++,c++11,atomic,C++,C++11,Atomic,我今天需要做的原子操作是相当棘手的,我想得到一些帮助。简而言之,我希望以原子方式执行以下操作: /* begin of atomicity */ if (--counter == 0) { Widget* widget = nullptr; swap(some_widget, widget); /* end of atomicity */ // use local 'widget' here } /* end of atomicity */ 我了解C++11原子和

我今天需要做的原子操作是相当棘手的,我想得到一些帮助。简而言之,我希望以原子方式执行以下操作:

/* begin of atomicity */
if (--counter == 0)
{
   Widget* widget = nullptr;

   swap(some_widget, widget);

   /* end of atomicity */

   // use local 'widget' here
}
/* end of atomicity */
我了解C++11原子和本质。前面的代码只是伪代码,旨在显示我希望在原子上发生的事情。我知道一个解决方案是让计数器有一个“转换”状态(例如0xFFFFFF),只改变它的值,先移动到这个转换,然后再移动到一个新的值:它本质上类似于自旋锁。你知道如何有效地做到这一点吗(即没有自旋锁,没有互斥锁,可能也没有等待)


非常感谢。

假设C++11,您希望执行原子获取和添加,然后处理结果

例如:

std::atomic<int> counter = 20;

if (counter.fetch_sub(1) == 1) /* return value is old value */
{
   Widget* widget = nullptr;
   swap(some_widget, widget);
}

原子性有两个终结点,哪一个是真正的终结点?我怀疑是否有任何方法可以在atomic中执行多个语句而不使用lock。此外,您不想删除
某些小部件
,您只想将其分配给
nullptr
?这正是我现在拥有的代码,但减量和交换不是atomic的。在递减之后,其他线程可能会更改“some_widget”指针,我就有了一个竞争。在这种情况下,为什么不使用“双重检查锁”方法呢?它将允许快速减量而无需锁定,但可以避免交换问题。我将对其进行编码,然后将其发布。编辑我的答案以包含上述内容。感谢您的努力,但我恐怕这无法回答问题。首先,它使用互斥锁,对于我打算做的事情来说是不可接受的。其次,首先检查计数器是否大于1,然后检查计数器。fetch_sub(1)==1为真。若计数器为1,且无其他情况发生,该怎么办?第一个if失败,计数器从不递减。我知道我的代码不完整,但我主要是想展示这个概念。通过首先执行一个检查,您可以将互斥锁的锁定/解锁从主代码路径中移除——这将大大提高性能,并减少对“我不能使用锁”语句的需要。如果您真的不能使用锁,那么您可能需要一种完全不同的机制来减少或消除线程之间的交互。在这种情况下,我需要更多的帮助。
std::atomic<int> counter = 20;
std::mutex  counterLock;
std::atomic<Widget*> some_widget;

...

if (counter.load(std::memory_order_acquire) > 5) /* first check whether we're "close enough" */
{
  /* only lock when needed */
  std::lock_guard<std::mutex> templock(counterLock); /* free lock whenever we exit this scope */
  if (counter.fetch_sub(1) == 1) /* return value is old value */
  {
    Widget* oldwidgetpr = some_widget.exchange(nullptr, std::memory_ordering_release);
    /* do whatever you need to do with the oldwidgetptr */
  }
}
else
  counter.fetch_sub(1);