2019独角兽企业重金招聘Python工程师标准>>>
自旋锁 通过cas操作,在大部分情况下可以实现比std::mutex 更高的性能
基本思想是通过原子操作去尝试获取变量的值 所有线程去竞争 该原子变量
性能:
spin_lock_init,无竞争情况下
1.spin_lock 16000W 次每秒
2.mutex 2800W次每秒
3.std::atomic<int> 24100W 次每秒
可见 自旋锁性能挺高的
spinlockirqsave?5个线程竞争情况下
1.spin_lock 717W 每秒
2.mutex 509W 每秒
3.atomic<int> 5900W 每秒
高竞争情况下 还是比mutex 性能高
c++自旋锁?
贴上代码
调整原子操作的内存顺序 可以再次加强性能,暂时用默认方式处理把
/*
Email me@dreamyouxi.com自旋锁*/
#pragma once
#include <atomic>
#include <thread>
#include <chrono>//cas
class spin_lock
{
private:std::atomic<bool> _internal_tag = false;
private:spin_lock(const spin_lock &) = delete;spin_lock& operator = (const spin_lock&) = delete;
public:void lock();void unlock();
};class spin_lock_guard
{spin_lock & locker;// ref
public:spin_lock_guard(spin_lock& lock);~spin_lock_guard();
};
#include "util/log.h"
#include "concurrency/spin_lock.h"
const char LOG_NAME[] = "spin_lock";
using namespace std;void spin_lock::lock()
{bool except = false;int times = 0;//fast passwhile (true){if (_internal_tag.compare_exchange_strong(except, true, std::memory_order_seq_cst)){//ok got itreturn;}if (++times > 4000){//break;}except = false;}times = 0;//slow passwhile (true){if (_internal_tag.compare_exchange_strong(except, true, std::memory_order_seq_cst)){//ok got itreturn;}if (++times < 1000){//this_thread::yield();}else{break;}except = false;}// //very slow passwhile (true){if (_internal_tag.compare_exchange_strong(except, true, std::memory_order_seq_cst)){//ok got itreturn;}except = false;//内存延时 6代E5 大概是100纳秒一个周期//mutex 无竞争情况下 性能大概是每秒300W 次 即 0.3微秒 300纳秒//sleep_for 进度在win平台好像最小是1MS 因此这里的设定也许有BUGthis_thread::sleep_for(std::chrono::nanoseconds(300));}
}void spin_lock::unlock()
{_internal_tag.store(false, std::memory_order_seq_cst);
}spin_lock_guard::spin_lock_guard(spin_lock& lock) :
locker(lock)
{locker.lock();
}spin_lock_guard::~spin_lock_guard()
{locker.unlock();
}
自旋锁使用,最高性能版本
/*
Email me@dreamyouxi.com自旋锁*/
#pragma once
#include <atomic>
#include <thread>
#include <chrono>//cas
class spin_lock
{std::atomic_flag locker = ATOMIC_FLAG_INIT; // NOLINT
public:spin_lock(const spin_lock &) = delete;spin_lock& operator = (const spin_lock&) = delete;spin_lock() = default;void unlock(){locker.clear(std::memory_order_release);}void lock();
private:bool try_lock(){bool ok = locker.test_and_set(std::memory_order_acquire);return !ok;}
};class spin_lock_guard
{spin_lock & locker;// ref
public:spin_lock_guard(spin_lock& lock);~spin_lock_guard();
};#include "util/log.h"
#include "concurrency/spin_lock.h"
const char LOG_NAME[] = "spin_lock";
using namespace std;void spin_lock::lock()
{int times = 0;//fast passwhile (true){if (try_lock()){//ok got itreturn;}if (++times > 4000){//break;}}times = 0;//slow passwhile (true){if (try_lock()){//ok got itreturn;}if (++times < 1000){//this_thread::yield();}else{break;}}// //very slow passwhile (true){if (try_lock()){//ok got itreturn;}//内存延时 6代E5 大概是100纳秒一个周期//mutex 无竞争情况下 性能大概是每秒300W 次 即 0.3微秒 300纳秒//sleep_for 进度在win平台好像最小是1MS 因此这里的设定也许有BUGthis_thread::sleep_for(std::chrono::nanoseconds(300));}
}spin_lock_guard::spin_lock_guard(spin_lock& lock) :
locker(lock)
{locker.lock();
}spin_lock_guard::~spin_lock_guard()
{locker.unlock();
}