给定以下示例代码:
int var;
int mvar;
std::mutex mvar_mutex;
void f(){
mvar_mutex.lock();
mvar = var * var;
mvar_mutex.unlock();
}
我想表达的是mvar_mutex
绑定到变量mvar
并且只保护该变量。 mvar_mutex
不应该保护var
,因为它没有被绑定到var
。 因此编译器允许将上述代码转换为下面的代码:
int var;
int mvar;
std::mutex mvar_mutex;
void f(){
int r = var * var; //possible data race created if binding is not known
mvar_mutex.lock();
mvar = r;
mvar_mutex.unlock();
}
当持有锁时,减少工作量可能会降低锁的争用。
对于int
类型,可以使用std::atomic<int> mvar;
并删除mvar_mutex
,但对于其他类型,例如std::vector<int>
,这是不可能的。
我该如何表达互斥变量绑定,以便C++编译器理解它并进行优化?可以允许在任何未绑定到该互斥体的变量上对其进行重新排序。
由于代码是使用clang :: ASTConsumer
和clang :: RecursiveASTVisitor
生成的,因此我愿意使用非标准扩展和AST操作,只要clang(理想情况下是clang 4.0)支持它们,并且生成的代码不需要优雅或可读。
编辑:由于这似乎引起了困惑:上述转换在C ++中是不合法的。互斥体与变量的描述绑定不存在。问题是如何实现这一点或达到相同的效果。
mvar
。 - Hatted Roosterlock_guard
ж€–unique_lock
代替手动锁定和解锁锁。 - Paul Rooneymutex.lock
创建了一个屏障,使得代码可以向下移动,但不能向上移动。mutex.unlock
创建了一个屏障,使得代码可以向上移动,但不能向下移动。(屏障不能穿过屏障)。我想修改它,使得这些屏障只适用于特定的对象,而其他代码可以自由地移动。例如,如果这些函数可以实现所需的重新排序行为,将mutex.lock
替换为acquire_barrier<mvar>();
,并将mutex.unlock
替换为release_barrier<mvar>();
将是一种可接受的解决方案。 - nwpstd::atomic
和无锁算法应该能够满足您的需求。 - Andrey Nasonov