C++ mutex&&RWlock

1. 读写锁,写优先

原文:https://blog.csdn.net/mymodian9612/article/details/52794980

#include <mutex>

#include <condition_variable>

 

#ifndef __KLOCWORK__

class WfirstRWLock

{

public:

    WfirstRWLock() = default;

    ~WfirstRWLock() = default;

public:

    void lock_read()

    {

        std::unique_lock<std::mutex> ulk(counter_mutex);

        cond_r.wait(ulk, [=]()->bool {return write_cnt == 0; });

        ++read_cnt;

    }

    void lock_write()

    {

        std::unique_lock<std::mutex> ulk(counter_mutex);

        ++write_cnt;

        cond_w.wait(ulk, [=]()->bool {return read_cnt == 0 && !inwriteflag; });

        inwriteflag = true;

    }

    void release_read()

    {

        std::unique_lock<std::mutex> ulk(counter_mutex);

        if (--read_cnt == 0 && write_cnt > 0)

        {

            cond_w.notify_one();

        }

    }

    void release_write()

    {

        std::unique_lock<std::mutex> ulk(counter_mutex);

        if (--write_cnt == 0)

        {

            cond_r.notify_all();

        }

        else

        {

            cond_w.notify_one();

        }

        inwriteflag = false;

    }

 

private:

    volatile size_t read_cnt{ 0 };

    volatile size_t write_cnt{ 0 };

    volatile bool inwriteflag{ false };

    std::mutex counter_mutex;

    std::condition_variable cond_w;

    std::condition_variable cond_r;

};

 

template <typename _RWLockable>

class unique_writeguard

{

public:

    explicit unique_writeguard(_RWLockable &rw_lockable)

        : rw_lockable_(rw_lockable)

    {

        rw_lockable_.lock_write();

    }

    ~unique_writeguard()

    {

        rw_lockable_.release_write();

    }

private:

    unique_writeguard() = delete;

    unique_writeguard(const unique_writeguard&) = delete;

    unique_writeguard& operator=(const unique_writeguard&) = delete;

private:

    _RWLockable &rw_lockable_;

};

template <typename _RWLockable>

class unique_readguard

{

public:

    explicit unique_readguard(_RWLockable &rw_lockable)

        : rw_lockable_(rw_lockable)

    {

        rw_lockable_.lock_read();

    }

    ~unique_readguard()

    {

        rw_lockable_.release_read();

    }

private:

    unique_readguard() = delete;

    unique_readguard(const unique_readguard&) = delete;

    unique_readguard& operator=(const unique_readguard&) = delete;

private:

    _RWLockable &rw_lockable_;

};

#endif

 

2. std::mutex(C++11)

原文:https://zh.cppreference.com/w/cpp/thread/mutex

 

mutex 类是能用于保护共享数据免受从多个线程同时访问的同步原语。

mutex 提供排他性非递归所有权语义:

调用方线程从它成功调用 lock try_lock开始,到它调用 unlock为止占有 mutex 

线程占有 mutex 时,所有其他线程若试图要求 mutex 的所有权,则将阻塞(对于lock 的调用)或收到 false 返回值(对于 try_lock.

调用方线程在调用 lock try_lock 前必须不占有 mutex 

 mutex 在仍为任何线程所占有时即被销毁,或在占有 mutex 时线程终止,则行为未定义。

std::mutex 既不可复制亦不可移动。

 

lock

锁定互斥,若互斥不可用则阻塞
(公开成员函数)

try_lock

尝试锁定互斥,若互斥不可用则返回
(公开成员函数)

unlock

解锁互斥
(公开成员函数)

 

注意

通常不直接使用 std::mutex ,std::unique_lockstd::lock_guard  std::scoped_lock (C++17 )以更加异常安全的方式管理锁定。

3. std::condition_variable(C++11)

原文:https://zh.cppreference.com/w/cpp/thread/condition_variable

condition_variable 类是同步原语,能用于阻塞一个线程,或同时阻塞多个线程,直至另一线程修改共享变量(条件)并通知 condition_variable 。

有意修改变量的线程必须:

1.获得 std::mutex (典型地通过 std::lock_guard )

2.在保有锁时进行修改

3. std::condition_variable 上执行 notify_one 或 notify_all (不需要为通知保有锁)

即使共享变量是原子的,也必须在互斥下修改它,以正确地发布修改到等待的线程。

任何有意在 std::condition_variable 上等待的线程必须:

1.获得 std::unique_lock<std::mutex> ,在与用于保护共享变量者相同的互斥上

2.执行 wait 、 wait_for 或 wait_until ,等待操作自动释放互斥,并悬挂线程的执行。

3.condition_variable 被通知时,时限消失或虚假唤醒发生,线程被唤醒,且自动重获得互斥。之后线程应检查条件,若唤醒是虚假的,则继续等待。

std::condition_variable 只可与 std::unique_lock<std::mutex> 一同使用;此限制在一些平台上允许最大效率。 std::condition_variable_any 提供可与任何基本可锁定 (BasicLockable) 对象,例如 std::shared_lock 一同使用的条件变量。

condition_variable 容许 wait 、 wait_for 、 wait_until 、 notify_one 及 notify_all 成员函数的同时调用。

std::condition_variable 是标准布局类型 (StandardLayoutType) 。它不可复制构造 (CopyConstructible) 、可移动构造 (MoveConstructible) 、可复制赋值 (CopyAssignable) 或可移动赋值 (MoveAssignable) 。

 

notify_one

通知一个等待的线程

notify_all

通知所有等待的线程

wait

阻塞当前线程,直到条件变量被唤醒

wait_for

阻塞当前线程,直到条件变量被唤醒,或到指定时限时长后

wait_until

阻塞当前线程,直到条件变量被唤醒,或直到抵达指定时间点

 

#include <iostream>

#include <string>

#include <thread>

#include <mutex>

#include <condition_variable>

 

std::mutex m;

std::condition_variable cv;

std::string data;

bool ready = false;

bool processed = false;

 

void worker_thread()

{

    // 等待直至 main() 发送数据

    std::unique_lock<std::mutex> lk(m);

    cv.wait(lk, []{return ready;});

 

    // 等待后,我们占有锁。

    std::cout << "Worker thread is processing data\n";

    data += " after processing";

 

    // 发送数据回 main()

    processed = true;

    std::cout << "Worker thread signals data processing completed\n";

 

    // 通知前完成手动解锁,以避免等待线程才被唤醒就阻塞(细节见 notify_one

    lk.unlock();

    cv.notify_one();

}

 

int main()

{

    std::thread worker(worker_thread);

 

    data = "Example data";

    // 发送数据到 worker 线程

    {

        std::lock_guard<std::mutex> lk(m);

        ready = true;

        std::cout << "main() signals data ready for processing\n";

    }

    cv.notify_one();

 

    // 等候 worker

    {

        std::unique_lock<std::mutex> lk(m);

        cv.wait(lk, []{return processed;});

    }

    std::cout << "Back in main(), data = " << data << '\n';

 

    worker.join();

}

posted on 2020-03-14 11:04  SunnyPoem  阅读(781)  评论(0编辑  收藏  举报