实现自旋锁

在这里插入图片描述

自旋锁,不进行阻塞,空耗CPU资源。

在针对多核CPU、资源占用时间不长的情况下很高效。
要求:锁住的资源足够小,计算时间足够短。

优点:相对于互斥锁,不会使我们的线程陷入内核态,效率高
缺点:如果资源每个线程对资源占用时间比较长,那么我们自旋操作将会大量的空耗CPU,效率低下。同时,对于单核CPU来说,自旋锁在自旋时进行大量空耗等待对方线程释放锁,然而单核CPU一次只能运行一个线程,因此,等待当前线程时间片到达切换之后,该自旋锁才会释放。

#include <iostream>
#include <atomic>
#include <thread>

using namespace std;

class CAS	// 自旋锁
{
private:
	std::atomic<bool> flag;	// true 加锁、false 无锁
public:
	// 注意这里的初值,初值为false。则第一 lock() 不锁,第二个进程 lock时会锁住。知道另一个进程unlock()
	// 如果初值为 true,那么第一调用lock(),就会阻塞。知道调用unlock().
	CAS(int _flag = false) :flag(_flag) {}	
	~CAS() {}
	CAS(const CAS&) = delete;
	CAS& operator=(const CAS&) = delete;

	void lock()	// 加锁
	{
		bool expect = false;	// 原子地比较
		/*  expected, desired,std::memory_order success,
                              std::memory_order failure
		参数会要求在这里传入期待的数值和新的数值。它们对比变量的值和期待的值是否一致,
			- 如果是,则替换为用户指定的一个新的数值。
			- 如果不是,则将变量的值和期待的值交换。
		如果 *this == expected 则 *this = desired ,返回true
		否则 *this != expected 则 expected = *this,返回false
		*/
		while (!flag.compare_exchange_strong(expect, true))
		{
			/* 
			加锁操作:当前为假,才能加锁
			
			如果 flag 为false ,则 flag == expect ,falg 被设置为 true。 同时语句返回假,退出。 

			如果 flag 为true , 即 flag != expect, expect被修改为 true。 然而循环体内又把 expect 修改为false,就会一直循环的执行,直至加锁。

			加锁成功的条件是,执行了 unlock() ,将falg设置为false
			*/
			expect = false;
		}
	}
	void unlock()
	{	// 原子地赋值/写操作
		// 原子地以非原子对象替换原子对象的值 
		flag.store(false);
	}
};

int num = 0;
CAS sm;

void fun()
{
	for (int i = 0; i < 100000; ++i)
	{
		sm.lock();	// 锁资源的消耗代价非常小,无需进行内核态与用户态的转态转换(线程切换),来锁资源
		++num;
		sm.unlock();
	}
}

int main()
{
	thread t1(fun), t2(fun);

	t1.join();
	t2.join();

	cout << num << endl;	// 理论上的值为 2000

	return 0;
}

2021/8/27更新…

#include <iostream>
#include <atomic>
#include <thread>

using namespace std;

class CAS	// 自旋锁
{
private:
	std::atomic<bool> flag;	// true 加锁、false 无锁
public:
	CAS(int _flag = false) :flag(_flag) {}
	~CAS() {}
	CAS(const CAS&) = delete;
	CAS& operator=(const CAS&) = delete;

	void lock()	// 加锁
	{
		bool expect = false;
		while (!flag.compare_exchange_strong(expect, true))
		{
			expect = false;
		}
	}
	void unlock()	{ flag.store(false); }
};




class Foo {
	CAS cas_1{ true };	// 就地初始化,等号,或花括号
	CAS cas_2{ true };
public:

	void first() {
		cout << "First" << endl;
		cas_1.unlock();     // 解锁
	}

	void second() {
		cas_1.lock();
		cout << "Second" << endl;
		cas_2.unlock();
	}

	void third() {
		cas_2.lock();
		cout << "Third" << endl;
	}
};


int main()
{
	Foo foo;

	// 线程执行顺序 First、Second、Third
	thread t1(&Foo::first, &foo);
	thread t2(&Foo::second, &foo);
	thread t3(&Foo::third, &foo);

	t1.join();
	t2.join();
	t3.join();

	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫RT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值