spin lock自旋锁

自旋锁 通过cas操作,在大部分情况下可以实现比std::mutex 更高的性能

基本思想是通过原子操作去尝试获取变量的值 所有线程去竞争 该原子变量

性能:

无竞争情况下

1.spin_lock 16000W 次每秒

2.mutex 2800W次每秒

3.std::atomic<int> 24100W 次每秒

可见 自旋锁性能挺高的

5个线程竞争情况下

1.spin_lock 717W 每秒

2.mutex 509W 每秒

3.atomic<int>  5900W 每秒

高竞争情况下 还是比mutex 性能高

011309016da3286af07ee3dd470edd4f8c0.jpg

 

贴上代码

调整原子操作的内存顺序 可以再次加强性能,暂时用默认方式处理把

/*
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 pass
	while (true)
	{
		if (_internal_tag.compare_exchange_strong(except, true, std::memory_order_seq_cst))
		{
			//ok got it
			return;
		}
		if (++times > 4000)
		{
			//
			break;
		}
		except = false;
	}
	times = 0;
	//slow pass
	while (true)
	{
		if (_internal_tag.compare_exchange_strong(except, true, std::memory_order_seq_cst))
		{
			//ok got it
			return;
		}
		if (++times < 1000)
		{
			//
			this_thread::yield();
		}
        else
        {
           break;
        }
		except = false;
	}
	// 
	//very slow pass
	while (true)
	{
		if (_internal_tag.compare_exchange_strong(except, true, std::memory_order_seq_cst))
		{
			//ok got it
			return;
		}
		except = false;
		//内存延时 6代E5 大概是100纳秒一个周期
		//mutex 无竞争情况下 性能大概是每秒300W 次 即 0.3微秒 300纳秒
		//sleep_for 进度在win平台好像最小是1MS 因此这里的设定也许有BUG
		this_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 pass
	while (true)
	{
		if (try_lock())
		{
			//ok got it
			return;
		}
		if (++times > 4000)
		{
			//
			break;
		}
	}
	times = 0;
	//slow pass
	while (true)
	{
		if (try_lock())
		{
			//ok got it
			return;
		}
		if (++times < 1000)
		{
			//
			this_thread::yield();
		}
        else
        {
           break;
        }
	}
	// 
	//very slow pass
	while (true)
	{
		if (try_lock())
		{
			//ok got it
			return;
		}
		//内存延时 6代E5 大概是100纳秒一个周期
		//mutex 无竞争情况下 性能大概是每秒300W 次 即 0.3微秒 300纳秒
		//sleep_for 进度在win平台好像最小是1MS 因此这里的设定也许有BUG
		this_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();
}

 

转载于:https://my.oschina.net/kkkkkkkkkkkkk/blog/2221516

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值