c++ 自旋锁、读写锁和可打断锁

本文介绍了自旋锁的原理和适用场景,以及使用互斥锁和条件变量实现的读写锁,以及可打断锁的设计,重点讲解了这些同步机制在并发编程中的重要性和使用时机。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自旋锁

// 自旋锁: 一种非阻塞同步机制,它通过原子操作来获取锁,如果锁已经被其他线程持有,则自旋等待直到锁可用。
// 适用场景: 保护短暂代码块,在等待锁的时间非常短的情况下,自旋锁可以提供更好的性能。
#ifndef _ZD_SPINLOCK_H_
#define _ZD_SPINLOCK_H_

#if defined(_MSC_VER) && _MSC_VER>1000
#pragma once
#endif

#include <atomic>

class ZDSpinLock
{
public:
	ZDSpinLock() 
		: m_lock(ATOMIC_VAR_INIT(false))
	{
	}

    virtual ~ZDSpinLock() = default;

    void Lock() 
    {
        // exchange函数作用:读m_lock,修改m_lcok为true,此过程为原子操作
        while (m_lock.exchange(true, std::memory_order_acquire)) 
        {
            // 锁被占用,自旋等待直至锁释放
        }
    }

    void UnLock() 
    {
        // store函数作用:修改m_lock为false,此过程为原子操作
        m_lock.store(false, std::memory_order_release);
    }

private:
	std::atomic_bool m_lock;
};

#endif

读写锁

// 使用互斥锁和条件变量实现读写锁
#ifndef _ZD_RWLOCK_H_
#define _ZD_RWLOCK_H_

#if defined(_MSC_VER) && _MSC_VER>1000
#pragma once
#endif

#include <mutex>
#include <condition_variable>

class ZDRWLock
{
public:
	ZDRWLock()
		: m_count_(0) 
		, m_writing_(false)
	{
	}

	virtual ~ZDRWLock() = default;

	void LockRead()
	{
		std::unique_lock<std::mutex> lock(m_mtx_);
		while (m_writing_)
		{
			m_cond_.wait(lock); // 有线程在写,阻塞读线程,注意:写优先级高于读
		}
		m_count_++;             // m_count >= 0, 允许多线程读
	}

	void UnLockRead()
	{
		std::unique_lock<std::mutex> lock(m_mtx_);
		m_count_--;
		if (0 == m_count_)        // 所有线程读完
		{
			m_cond_.notify_one(); // 唤醒一个读或写线程
		}
	}

	void LockWrite()
	{
		std::unique_lock<std::mutex> lock(m_mtx_);
		while (m_writing_ || m_count_ > 0) // 有多个线程在读或单个线程在写,等待
		{
			m_cond_.wait(lock);
		}
		m_writing_ = true;        // 单线程写
	}

	void UnLockWrite()
	{
		std::unique_lock<std::mutex> lock(m_mtx_);
		m_writing_ = false;         // 线程写完
		m_cond_.notify_all();       // 唤醒所有的读写线程
	}

private:
	std::mutex m_mtx_;
	std::condition_variable m_cond_;

	// volatile告诉编译器被其修饰的变量可能被多个线程同时访问, 因此不要对该变量进行优化,以确保线程之间可以正确的读取和写入该值
	volatile int m_count_;
	volatile bool m_writing_;
};

#endif

可打断锁

// 可打断锁: 一种能够响应其他线程的中断请求的锁
// 使用场景: 陷入内核等待的线程可被打断
#ifndef _ZD_INTERRUPTLOCK_H_
#define _ZD_INTERRUPTLOCK_H_

#if defined(_MSC_VER) && _MSC_VER>1000
#pragma once
#endif

#include <mutex>
#include <condition_variable>
#include <atomic>

class ZDInterruptLock
{
public:
	ZDInterruptLock()
	{
	}

	virtual ~ZDInterruptLock() = default;

	void Lock() 
	{
		std::unique_lock<std::mutex> lock(m_mtx_);
		m_status = 0;
		m_cond_.wait(lock, [&] { return 0 != m_status; });
	}

	bool TryLock() 
	{
		std::unique_lock<std::mutex> lock(m_mtx_);
		if (0 != m_status)
		{
			m_status = 0;
			return true;
		}

		return false;
	}

	void UnLock() 
	{
		{
			std::lock_guard<std::mutex> lock(m_mtx_);
			m_status = 1;
		}
		m_cond_.notify_one(); 
	}

	void Interrupt() 
	{
		{
			std::lock_guard<std::mutex> lock(m_mtx_);
			m_status = 2;
		}
		m_cond_.notify_all();
	}


	bool IsInterrupt() const 
	{
		std::lock_guard<std::mutex> lock(m_mtx_);
		return 2 == m_status;
	}

private:
	mutable std::mutex m_mtx_;
	std::condition_variable m_cond_;
	std::atomic<int> m_status;
};

#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值