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