基于多线程并发-原子量实现自旋锁

一、数据竞争的两种处理方式

多线程的核心是CPU的时间分片,同一时刻只能有一个线程获取到锁。对于没有获取到锁的线程通常有两种处理方式:自旋锁,没有获取到锁的线程会一直循环等待判断资源是否已经释放锁,不用将线程阻塞起来;互斥锁,把未获取到锁的线程阻塞起来,等待重新调度请求。

二、什么是自旋锁?

1、自旋锁属于busy-waiting(轮询等待)类型锁。
2、自旋锁最多只能被一个可执行线程持有。
3、如果一个可执行线程试图获得一个被其它线程持有的自旋锁,那么线程就会一直进行忙等待,自旋(空转),被阻塞线程依然不会让出CPU,等待自旋锁重新可用。如果自旋锁未被争用,请求锁的执行线程便立刻得到自旋锁,继续执行。
4、获取锁的线程一直处于活跃状态,但并没有执行任何有效的任务,使用自旋锁会造成busy-waiting。
5、自旋锁不会使线程状态发生切换,一直处于用户态,即线程一直都是active的。
6、不会使线程进入阻塞状态,减少了不必要的上下文切换,自旋锁主要适用于线程占有锁得时间短的场景

三、自旋锁实现

C++11 版不带自旋锁的API,以下为实现示例(基于原子)

#include <atomic>
class spinlock_mutex
{
private:
	spinlock_mutex(const spinlock_mutex&) = delete;
	spinlock_mutex& operator=(const spinlock_mutex) = delete;
	
public:
	spinlock_mutex() = default;
	void lock()
	{
		while (flag.test_and_set(std::memory_order_acquire));
	}
	void unlock()
	{
		flag.clear(std::memory_order_release);
	}

private:
	std::atomic_flag flag;
};

说明:atomic_flag是原子操作的,获得锁后会把此变量置为true,然后另外一个线程就会因为flag=true而一直在while处执行循环,直到获得锁的线程将锁释放(将falg置为false),此时线程的flag.test_and_set()就会返回false,跳出while循环,并把flag置为true。

四、使用示例

#include <chrono>
#include <iostream>
#include <string>
#include <mutex>
void func(std::string str)
{
	splock.lock();
	//do things
	for (int i = 0; i < 100; ++i)
	{
		std::cout << str << std::endl;
		//std::this_thread::sleep_for(std::chrono::milliseconds(100));
	}
	splock.unlock();
}
int main()
{
	std::cout << "程序开始执行" << std::endl;
	std::thread t1(func, "thing one");
	std::thread t2(func, "thing two");
	std::thread t3(func, "thing three");
	t1.join();
	t2.join();
	t3.join();
	return 0;
}
说明:传入的func函数字符串一旦被输出,就一定会连续输出100个,即表明对for循环加锁成功。

如有错误或不足欢迎评论指出!创作不易,转载请注明出处。如有帮助,记得点赞关注哦(⊙o⊙)
更多内容请关注个人博客:https://blog.csdn.net/qq_43148810

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大胡子的艾娃

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

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

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

打赏作者

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

抵扣说明:

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

余额充值