1. ScopedLockImpl三个规范接口
用于规范结构,内部保存锁引用对象,该规范可以自动完成作用域内的加锁和解锁,构造函数自动完成加锁,在作用域内实例化ScopedLockImpl
并传入一个已经实例化的锁对象,在构造函数完成加锁,在作用域结束后,被自动销毁,并调用析构函数完成解锁。全过程自动,非常好用👍
- 成员变量
T& m_mutex
:保存锁引用对象
- 成员变量
bool m_locked
:记录是否上锁
- 成员函数全部为
lock()
和unlock()
,但读写类型的锁在内部调用的是锁引用对象的rdlock()
、wrlock()
、unlock()
1.1 ScopedLockImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| template<class T> struct ScopedLockImpl { public: ScopedLockImpl(T& mutex) :m_mutex(mutex) { m_mutex.lock(); m_locked = true; } ~ScopedLockImpl() { unlock(); }
void lock() { if (!m_locked) { m_mutex.lock(); m_locked = true; } }
void unlock() { if (m_locked) { m_mutex.unlock(); m_locked = false; } } private: T& m_mutex; bool m_locked; };
|
1.2 ReadScopedLockImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| template<class T> struct ReadScopedLockImpl { public: ReadScopedLockImpl(T& mutex) :m_mutex(mutex) { m_mutex.rdlock(); m_locked = true; } ~ReadScopedLockImpl() { unlock(); }
void lock() { if (!m_locked) { m_mutex.rdlock(); m_locked = true; } }
void unlock() { if (m_locked) { m_mutex.unlock(); m_locked = false; } } private: T& m_mutex; bool m_locked; };
|
1.3 ScopedLockImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| template<class T> struct WriteScopedLockImpl { public: WriteScopedLockImpl(T& mutex) :m_mutex(mutex) { m_mutex.wrlock(); m_locked = true; } ~WriteScopedLockImpl() { unlock(); }
void lock() { if (!m_locked) { m_mutex.wrlock(); m_locked = true; } }
void unlock() { if (m_locked) { m_mutex.unlock(); m_locked = false; } } private: T& m_mutex; bool m_locked; };
|
2. 锁
2.1 Semaphore
信号量,保存一个非负整数
- 成员变量
sem_t
:记录信号量的值
- 成员函数
wait()
:使信号量增加
- 成员函数
notify()
:使信号量减少
- 构造函数完成信号量的初始化,析构函数完成信号量的销毁
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Semaphore { public: Semaphore(uint32_t count = 0); ~Semaphore(); void wait(); void notify(); private: Semaphore(const Semaphore&) = delete; Semaphore(const Semaphore&&) = delete; Semaphore& operator=(const Semaphore&) = delete; private: sem_t m_semaphore; };
|
2.2 Mutex
最简单的互斥锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Mutex { public: typedef ScopedLockImpl<Mutex> Lock; Mutex() { pthread_mutex_init(&m_mutex, nullptr); } ~Mutex() { pthread_mutex_destroy(&m_mutex); } void lock() { pthread_mutex_lock(&m_mutex); } void unlock() { pthread_mutex_unlock(&m_mutex); } private: pthread_mutex_t m_mutex; };
|
2.3 rwlock
读写锁内部有两个typedef
关键字,定义了ReadLock
和WriteLock
两个类型,提供了简单的读写锁作用域自动加锁解锁的功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class RWMutex { public: typedef ReadScopedLockImpl<RWMutex> ReadLock; typedef WriteScopedLockImpl<RWMutex> WriteLock; RWMutex() { pthread_rwlock_init(&m_lock, nullptr); } ~RWMutex() { pthread_rwlock_destroy(&m_lock); } void rdlock() { pthread_rwlock_rdlock(&m_lock); } void wrlock() { pthread_rwlock_wrlock(&m_lock); } void unlock() { pthread_rwlock_unlock(&m_lock); }
private: pthread_rwlock_t m_lock; };
|
2.4 Spinlock
自旋锁,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,避免一睡眠就被调度,降低性能。对于IO等待很长的适合用互斥,但是就等一瞬间的还是自旋效率高
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Spinlock { public: typedef ScopedLockImpl<Spinlock> Lock; Spinlock() { pthread_spin_init(&m_mutex, 0); } ~Spinlock() { pthread_spin_destroy(&m_mutex); } void lock() { pthread_spin_lock(&m_mutex); } void unlock() { pthread_spin_unlock(&m_mutex); } private: pthread_spinlock_t m_mutex; };
|
2.5 CASLock
原子操作改变atomic_flag m_mutex
,同样获得锁的时候自旋
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class CASLock { public: typedef ScopedLockImpl<CASLock> Lock; CASLock() { m_mutex.clear(); } ~CASLock() { } void lock() { while (std::atomic_flag_test_and_set_explicit(&m_mutex, std::memory_order_acquire)); } void unlock() { std::atomic_flag_clear_explicit(&m_mutex, std::memory_order_release); } private: volatile std::atomic_flag m_mutex; };
|
3. 使用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| sylar::RWMutex s_mutex; int pthread = 0;
void thread_fun() { for (int i = 0; i < 1000000; ++i) { sylar::RWMutex::WriteLock lock(s_mutex); ++pthread; } }
int main() { std::thread thread1(thread_fun); std::thread thread2(thread_fun); thread1.join(); thread2.join(); std::cout<<pthread<<std::endl; }
|
Author:
mxwu
Permalink:
https://mingxuanwu.com/2024/07/12/202407122005/
License:
Copyright (c) 2023 CC-BY-NC-4.0 LICENSE