SpinLock源码

一、概要

spinLock的基本原理是如果发现其他人锁着,就一直循环,知道其他人解锁后,再上锁。一般SpinLock适用于锁的时间很短的情况,通过不断判定是否可以加锁,避免适用Mutex这类操作系统锁带来不能锁定时的上下文切换。

二、实现源码

#pragma once
#include <atomic>
#include <thread>
using namespace std;
class SpinLock
{
    
    
private:
	atomic<bool> _flag;
public:
	SpinLock()
	{
    
    
		_flag = false;
	}
	void lock()
	{
    
    
		bool r = false;
		while (!_flag.compare_exchange_strong(r, true)) //如果_flag为false,就把_flag改为true,r改为false,并且保证_flag的获取和修改时原子的
		{
    
    
			r = false;
		}
	}
	void unlock()
	{
    
    
		_flag.store(false);
	}
};
class SpinLockTest
{
    
    
private:
	int count = 0;
	int spinCount = 0;
	int maxLoop = 10000000;
	SpinLock lock;
public:

	void doTest()
	{
    
    
		thread thread1([this](){
    
    this->process(); });
		thread thread2([this](){
    
    this->process(); });
		thread1.join();
		thread2.join();

		thread thread3([this]() {
    
    this->spinProcess(); });
		thread thread4([this]() {
    
    this->spinProcess(); });
		thread3.join();
		thread4.join();
		printf("count=%d spinCount=%d\n", count, spinCount);
		
	}
	void process()
	{
    
    
		for (int i = 0; i < maxLoop; i++)
		{
    
    
			count++;
		}
	}
	void spinProcess()
	{
    
    
		for (int i = 0; i < maxLoop; i++)
		{
    
    
			lock.lock();
			spinCount++;
			lock.unlock();
		}
	}
};

三、输出结果

count=13795495 spinCount=20000000

三、代码分析

  • 从结果看spinLock实现了对spinCount的原子操作,而普通的多线程累加不能保证原子。
  • 其中用到了Atomic。Atomic可以实现对基本类型数据的原子读、原子写以及CAS操作。CAS是一种比较交换,当前值和期望值一样时,就交换成目标值。这里涉及到对Atomic值的读和写,单一通过原子读和原子写不能保证整个读写是原子的。幸好,Atomic提供了CAS操作,CAS通过CPU级别的无锁操作,实现了对数据的原子读写,不会导致上下文切换,比Mutex这种操作系统级别的锁有数倍的性能提升。

猜你喜欢

转载自blog.csdn.net/gamekit/article/details/107294109