读写锁、自旋锁、信号量的C++实现/封装

2020/07/03 cpp_concurrency 共 4111 字,约 12 分钟

自旋锁

// spin_lock.h

// 自旋锁
class spin_lock
{
public:
    spin_lock();
    ~spin_lock();
    void lock();
    void unlock();

private:
    pthread_spinlock_t m_lock;
};
// spin_lock.cc

// 自旋锁
spin_lock::spin_lock()
{
    int ret = pthread_spin_init(&m_lock, 0);
    s_assert_errno(ret == 0, "pthread_spin_init error", ret);
}

spin_lock::~spin_lock()
{
    int ret = pthread_spin_destroy(&m_lock);
    s_assert_errno(ret == 0, "pthread_spin_destroy error", ret);
}

void spin_lock::lock()
{
    int ret = pthread_spin_lock(&m_lock);
    s_assert_errno(ret == 0, "pthread_spin_lock error", ret);
}

void spin_lock::unlock()
{
    int ret = pthread_spin_unlock(&m_lock);
    s_assert_errno(ret == 0, "pthread_spin_unlock error", ret);
}

信号量

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

// 禁止拷贝,如果要在多线程中共享,则使用共享指针
class std_semaphore : public noneCopy
{
public:
    using _Mutex = std::mutex;
    using _Condition = std::condition_variable;

    explicit std_semaphore(const int count) : m_counter(count) {}
    ~std_semaphore() {}

    void wait();
    void signal();

private:
    std::atomic<int> m_counter;
    _Mutex m_mutex;
    _Condition m_condition;
};
// 禁止拷贝,如果要在多线程中共享,则使用共享指针
void std_semaphore::wait()
{
    std::unique_lock<_Mutex> ulock(m_mutex);
    --m_counter;
    m_condition.wait(ulock, [this]()
                        { return this->m_counter >= 0; });
}

void std_semaphore::signal()
{
    std::unique_lock<_Mutex> ulock(m_mutex);
    ++m_counter;
    m_condition.notify_one();
}

读写锁

mutex辅助类

template <typename _Mutex>
class scope_lock : public noneCopy
{
public:
    explicit scope_lock(_Mutex &mutex) : m_mutex(mutex)
    {
        m_mutex.lock();
    }

    ~scope_lock()
    {
        m_mutex.unlock();
    }
private:
    _Mutex &m_mutex;
};

Linux读写锁的封装

class read_write_lock
{
public:
    read_write_lock();
    read_write_lock(const read_write_lock &) = default;

    ~read_write_lock();
    void read_lock();
    void write_lock();
    void release_read();
    void release_write();
    void unlock();
private:
    pthread_rwlock_t m_rd_lock;
};
read_write_lock::read_write_lock()
{
    int ret = pthread_rwlock_init(&m_rd_lock, nullptr);
    if (ret != 0)
    {
        trace_throw("pthread_mutex_unlock error", ret);
    }
}

read_write_lock::~read_write_lock()
{
    int ret = pthread_rwlock_destroy(&m_rd_lock);
    if (ret != 0)
    {
        trace_throw("pthread_rwlock_destroy error", ret);
    }
}

void read_write_lock::read_lock()
{
    int ret = pthread_rwlock_rdlock(&m_rd_lock);
    if (ret != 0)
    {
        trace_throw("pthread_rwlock_rdlock error", ret);
    }
}

void read_write_lock::write_lock()
{
    int ret = pthread_rwlock_wrlock(&m_rd_lock);
    if (ret != 0)
    {
        trace_throw("pthread_rwlock_wrlock error", ret);
    }
}

void read_write_lock::release_read()
{
    unlock();
}

void read_write_lock::release_write()
{
    unlock();
}

void read_write_lock::unlock()
{
    pthread_rwlock_unlock(&m_rd_lock);
}

使用C++11标准库实现的读写锁,写优先

class write_priority_lock
{
public:
    explicit write_priority_lock()
    {
    }

    ~write_priority_lock() = default;

    void read_lock();
    void write_lock();

    // m_read_count 和 m_write_count 本身是原子的,因此不需要加锁
    void release_read();
    void release_write();

private:
    std::mutex m_mutex;
    std::condition_variable m_condition_read;
    std::condition_variable m_condition_write;
    bool m_is_in_write{false};
    std::atomic<int32_t> m_write_count{0};
    std::atomic<int32_t> m_read_count{0};
};
void write_priority_lock::read_lock()
{
    std::unique_lock<std::mutex> ulock(m_mutex);
    m_condition_read.wait(ulock, [this]() -> bool
                            { return this->m_write_count == 0; });
    m_read_count++;
}

void write_priority_lock::write_lock()
{
    std::unique_lock<std::mutex> ulock(m_mutex);
    m_write_count++;
    m_condition_write.wait(ulock, [this]() -> bool
                            { return this->m_write_count <= 1; });
}

// m_read_count 和 m_write_count 本身是原子的,因此不需要加锁
void write_priority_lock::release_read()
{
    if ((--m_read_count) <= 0 && m_write_count > 0)
    {
        m_condition_write.notify_one();
    }
}

void write_priority_lock::release_write()
{
    if (--m_write_count > 0)
    {
        m_condition_write.notify_one();
    }
    else if (m_read_count > 0)
    {
        m_condition_read.notify_all();
    }
}

读锁


template <typename _ReadLockType>
class scope_read_lock : public noneCopy
{
public:
    scope_read_lock(const _ReadLockType &lock) : m_lock(lock)
    {
        m_lock.read_lock();
    }
    ~scope_read_lock()
    {
        m_lock.release_read();
    }

private:
    _ReadLockType m_lock;
};

写锁

// 写锁
template <typename _WriteLockType>
class scope_write_lock : public noneCopy
{
public:
    scope_write_lock(const _WriteLockType &lock) : m_lock(lock)
    {
        m_lock.read_lock();
    }
    ~scope_write_lock()
    {
        m_lock.release_read();
    }

private:
    _WriteLockType m_lock;
};

文档信息

Search

    Table of Contents