我假设并发库是指 Microsoft 的并发运行时。您的用例实际上是一个关键部分,并且 Concurrency 提供了concurrency::critical_section
,这是一个不可重入互斥锁:
using namespace concurrency;
class particle
{
double param1;
. . .
critical_section particle_lck;
. . .
};
那么临界区就变成了:
currentParticle->particle_lck.lock();
currentParticle->param1 += anything;
currentParticle->particle_lck.unlock();
如果您更喜欢范围方法,请使用concurrency::critical_section::scoped_lock
:
{
critical_section::scoped_lock guard(currentParticle->particle_lck);
currentParticle->param1 += anything;
}
scoped_lock
是一个简单的包装器。它接受一个critical_section
对象的引用并在构造函数中调用lock()
,然后unlock()
在析构函数中调用,因此当它超出范围时它会释放锁。
正如 Jim Cownie 所解释的,将锁用于可以通过原子操作更有效地完成的事情是一种矫枉过正的做法。在 OpenMP 中,通常会这样做:
#pragma omp atomic update
currentParticle->param1 += anything;
标准 C++ 中的原子操作需要使用特殊的原子类型,而这些原子类型仅适用于从 C++20 开始的浮点类型,因此您的代码将是(假设 C++20 编译器):
#include <atomic>
class particle
{
std::atomic<double> param1;
. . .
};
更新值:
currentParticle->param1.fetch_add(anything, std::memory_order_relaxed);
并发不提供自己的原子类型。相反,它依赖于combinable
类来提供等效于 OpenMP 的reduction
子句。