• 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 ";

        data += " after processing";

        // 发送数据回 main()

        processed = true;

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

        // 通知前完成手动解锁,以避免等待线程才被唤醒就阻塞(细节见 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 ";

        }

        cv.notify_one();

        // 等候 worker

        {

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

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

        }

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

        worker.join();

    }

  • 相关阅读:
    1002. 查找常用字符
    1047. 删除字符串中的所有相邻重复项
    3. 无重复字符的最长子串
    剑指 Offer 57
    239. 滑动窗口最大值
    476. 数字的补数
    876. 链表的中间结点
    973. 最接近原点的 K 个点
    面试题 02.04. 分割链表
    1616. 分割两个字符串得到回文串
  • 原文地址:https://www.cnblogs.com/sunnypoem/p/12491030.html
Copyright © 2020-2023  润新知