Folly 的 MicroSpinLock 使用方法和实现
由 Facebook 开发和维护的 C++库 Folly
提供了自旋锁的实现folly::MicroSpinLock
,代码文件地址:https://github.com/facebook/folly/blob/master/folly/synchronization/MicroSpinLock.h。
folly::MicroSpinLock
小到只有一个字节,并且为POD
类型,也就是说它可以保存到文件,在(共享)内存中共享!
根据 Facebook 的测试,该自旋锁单次耗时约 13.5ns ,std::mutex
性能大约在 25ns ,参考的虚函数单次调用耗时约 1.7ns。
它的使用很简单,就是lock
和unlock
函数,也可以用std::lock_guard
来自动上锁和解锁(folly
提供MSLGuard
的typedef
):
folly::MicroSpinLock spinlock;
spinlock.lock();
// your work need to protect
spinlock.unlock();
{
// 已定义typedef std::lock_guard<MicroSpinLock> MSLGuard
MSLGuard guard{spinlock};
// your work need to protect
}
为了达到POD
的目的,folly::MicroSpinLock
只有一个uint8_t
类型的成员lock_
。但每次使用时,会强行转换成std::atomic
对象:
std::atomic<uint8_t>* payload() noexcept {
return reinterpret_cast<std::atomic<uint8_t>*>(&this->lock_);
}
我们细看lock
的实现:
void lock() noexcept {
detail::Sleeper sleeper;
while (!cas(FREE, LOCKED)) {
do {
sleeper.wait();
} while (payload()->load(std::memory_order_relaxed) == LOCKED);
}
assert(payload()->load() == LOCKED);
annotate_rwlock_acquired(
this, annotate_rwlock_level::wrlock, __FILE__, __LINE__);
}
这里面有三个地方需要展开说。
第一个是cas
,这个是std::atomic
提供的标准比较替换的原子实现:
bool cas(uint8_t compare, uint8_t newVal) noexcept {
return std::atomic_compare_exchange_strong_explicit(
payload(),
&compare,
newVal,
std::memory_order_acquire,
std::memory_order_relaxed);
}
这里用了对内存顺序要求最高的std::atomic_compare_exchange_strong_explicit
。具体原因和对效率的影响不太清楚。
第二个是用了detail::Sleeper
。最终实现了,前 4000 次检查失败时,会插入_mm_pause
空指令,但 4000 次之后,将休眠
0.5 毫秒,此时将让出 CPU ,线程被切换,避免总是占住 CPU。
因为每次只插入一条pause
空指令,所以 4000 次检查,不一定够。但不提供修改方式(除了改源代码)。
第三个是最后还调用了annotate_rwlock_acquired
这个函数。这个用于配合线程检查工具ThreadSanitizer
,检查多线程编程中是否有Data
Race
现象。
当用户没有开启选项时,该函数会被编译器优化掉,因此不用担心该行代码会降低性能。
作者暂无likerid, 赞赏暂由本网站代持,当作者有likerid后会全部转账给作者(我们会尽力而为)。Tips: Until now, everytime you want to store your article, we will help you store it in Filecoin network. In the future, you can store it in Filecoin network using your own filecoin.
Support author:
Author's Filecoin address:
Or you can use Likecoin to support author: