c++20 规范, vs2019 , 头文件 <mutex> ,注释以及几个探讨 (1)

(1 探讨一) mutex 这个名称的来源是 mutual exclusion :互相排斥。 mutex 与 recursive_mutex 的数据成员的定义如下:

在这里插入图片描述

测试如下:

在这里插入图片描述

运行以下:

在这里插入图片描述

以及:

在这里插入图片描述

(2 探讨二) recursive_mutex 仍然是锁,对不同线程中的加锁,仍然是竞争关系,同 mutex 。测试如下:

在这里插入图片描述

(3 探讨三) 同一线程中对 recursive_mutex 的加锁次数应该与解锁次数保持相同。否则是错误的,例如 调用 unlock() 次数少了,就会造成锁始终被本线程持有。

(4 探讨四) 这里给出 condition_variable . wait_for() 的使用例子:

在这里插入图片描述

结论: condition_variable . wait() 是只等待且只能有 condition_variable .notify() 唤醒;
condition_variable . wait_for() 是可以被 condition_variable .notify() 提前唤醒,或者睡眠到时间了且持有锁才醒来,即使用完了睡眠时间但无法抢到锁,依然会继续睡眠。再给个带断言函数的例子,如下图:

在这里插入图片描述

再给个例子,说明定时睡眠的线程只有再具有了锁才会超时苏醒,否则就是继续睡,超时了也继续睡:

在这里插入图片描述

这一切的缘由在源码里:

在这里插入图片描述

(5 探讨五) 对于 condition_variable 的成员函数:不带断言的 wait_for,返回值是超时返回或者未超时返回
带断言的 wait_for,返回值是断言的结果:true 或 false

在这里插入图片描述
以及:

在这里插入图片描述

(6 探讨六) 弄清 timed_mutex 的数据结构,对于理解其功能与使用,是有帮助的:

在这里插入图片描述

( 7 ) 接着给出 timed_mutex 的延时申请锁的使用例子:

在这里插入图片描述

( 8 探讨八) recursive_timed_mutex 类具有与 timed_mutex 完全相同的功能,且允许了同一线程对 recursive_timed_mutex 的重复加锁,而不报错。而对 timed_mutex 的 lock() 在同一线程的重复调用会导致程序出错。如下图:

在这里插入图片描述

谢谢

请帮我给这些代码加上注释 #pragma once #include <thread> #include <mutex> #include <vector> #include <queue> #include <atomic> #include <functional> #include <condition_variable> #include <map> #include <future> using namespace std; class ThreadPool { public: ThreadPool(int min = 4, int max = thread::hardware_concurrency()); ~ThreadPool(); void addTask(function<void()> f); template<typename F, typename... Args> auto addTask(F&& f, Args&&... args) -> future<typename result_of<F(Args...)>::type> { using returnType = typename result_of<F(Args...)>::type; auto task = make_shared<packaged_task<returnType()>>( bind(forward<F>(f), forward<Args>(args)...) ); future<returnType> res = task->get_future(); { unique_lock<mutex> lock(m_queueMutex); m_tasks.emplace([task]() { (*task)(); }); } m_condition.notify_one(); return res; } private: void manager(); void worker(); private: thread* m_manager; map<thread::id, thread> m_workers; vector<thread::id> m_ids; int m_minThreads; int m_maxThreads; atomic<bool> m_stop; atomic<int> m_curThreads; atomic<int> m_idleThreads; atomic<int> m_exitNumber; queue<function<void()>> m_tasks; mutex m_idsMutex; mutex m_queueMutex; condition_variable m_condition; }; #include "threadpool.h" #include <iostream> ThreadPool::ThreadPool(int min, int max) : m_maxThreads(max), m_minThreads(min), m_stop(false), m_exitNumber(0) { //m_idleThreads = m_curThreads = max / 2; m_idleThreads = m_curThreads = min; cout << "线程数量: " << m_curThreads << endl; m_manager = new thread(&ThreadPool::manager, this); for (int i = 0; i < m_curThreads; ++i) { thread t(&ThreadPool::worker, this); m_workers.insert(make_pair(t.get_id(), move(t))); } } ThreadPool::~ThreadPool() { m_stop = true; m_condition.notify_all(); for (auto& it : m_workers) { thread& t = it.second; if (t.joinable()) { cout << "******** 线程 " << t.get_id() << " 将要退出了..." << endl; t.join(); } } if (m_manager->joinable()) { m_manager->join(); } delete m_manager; } void ThreadPool::addTask(function<void()> f) { { lock_guard<mutex> locker(m_queueMutex); m_tasks.emplace(f); } m_condition.notify_one(); } void ThreadPool::manager() { while (!m_stop.load()) { this_thread::sleep_for(chrono::seconds(2)); int idle = m_idleThreads.load(); int current = m_curThreads.load(); if (idle > current / 2 && current > m_minThreads) { m_exitNumber.store(2); m_condition.notify_all(); unique_lock<mutex> lck(m_idsMutex); for (const auto& id : m_ids) { auto it = m_workers.find(id); if (it != m_workers.end()) { cout << "############## 线程 " << (*it).first << "被销毁了...." << endl; (*it).second.join(); m_workers.erase(it); } } m_ids.clear(); } else if (idle == 0 && current < m_maxThreads) { thread t(&ThreadPool::worker, this); cout << "+++++++++++++++ 添加了一个线程, id: " << t.get_id() << endl; m_workers.insert(make_pair(t.get_id(), move(t))); m_curThreads++; m_idleThreads++; } } } void ThreadPool::worker() { while (!m_stop.load()) { function<void()> task = nullptr; { unique_lock<mutex> locker(m_queueMutex); while (!m_stop && m_tasks.empty()) { m_condition.wait(locker); if (m_exitNumber.load() > 0) { cout << "----------------- 线程任务结束, ID: " << this_thread::get_id() << endl; m_exitNumber--; m_curThreads--; m_idleThreads--; unique_lock<mutex> lck(m_idsMutex); m_ids.emplace_back(this_thread::get_id()); return; } } if (!m_tasks.empty()) { cout << "取出一个任务..." << endl; task = move(m_tasks.front()); m_tasks.pop(); } } if (task) { m_idleThreads--; task(); m_idleThreads++; } } }
最新发布
11-16
C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:112:8: error: 'once_flag' in namespace 'std' does not name a type std::once_flag flag_; ^~~~~~~~~ C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:112:3: note: 'std::once_flag' is defined in header '<mutex>'; did you forget to '#include <mutex>'? C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:65:1: +#include <mutex> C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:112:3: std::once_flag flag_; ^~~ C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h: In constructor 'constexpr google::protobuf::internal::CallOnceInitializedMutex<T>::CallOnceInitializedMutex()': C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:100:42: error: class 'google::protobuf::internal::CallOnceInitializedMutex<T>' does not have any field named 'flag_' constexpr CallOnceInitializedMutex() : flag_{}, buf_{} {} ^~~~~ C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h: In member function 'T& google::protobuf::internal::CallOnceInitializedMutex<T>::get()': C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:108:10: error: 'call_once' is not a member of 'std' std::call_once(flag_, [&] { ::new (static_cast<void*>(&buf_)) T(); }); ^~~~~~~~~ C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:108:10: note: suggested alternative: 'all_of' std::call_once(flag_, [&] { ::new (static_cast<void*>(&buf_)) T(); }); ^~~~~~~~~ all_of C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:108:20: error: 'flag_' was not declared in this scope std::call_once(flag_, [&] { ::new (static_cast<void*>(&buf_)) T(); }); ^~~~~ C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h: At global scope: C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:136:33: error: 'mutex' is not a member of 'std' CallOnceInitializedMutex<std::mutex> mu_{}; ^~~~~ C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:136:33: note: 'std::mutex' is defined in header '<mutex>'; did you forget to '#include <mutex>'? C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:136:33: error: 'mutex' is not a member of 'std' C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:136:33: note: 'std::mutex' is defined in header '<mutex>'; did you forget to '#include <mutex>'? C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:136:38: error: template argument 1 is invalid CallOnceInitializedMutex<std::mutex> mu_{}; ^ C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h: In member function 'void google::protobuf::internal::WrappedMutex::Lock()': C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:126:47: error: request for member 'lock' in '((google::protobuf::internal::WrappedMutex*)this)->google::protobuf::internal::WrappedMutex::mu_', which is of non-class type 'int' void Lock() GOOGLE_PROTOBUF_ACQUIRE() { mu_.lock(); } ^~~~ C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h: In member function 'void google::protobuf::internal::WrappedMutex::Unlock()': C:/mycv/opencv/sources/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:127:49: error: request for member 'unlock' in '((google::protobuf::internal::WrappedMutex*)this)->google::protobuf::internal::WrappedMutex::mu_', which is of non-class type 'int' void Unlock() GOOGLE_PROTOBUF_RELEASE() { mu_.unlock(); } ^~~~~~报错咋解决
10-27
#ifndef GUIUTIL_H #define GUIUTIL_H #include <QtGlobal> #include <QString> #include <cmath> #include <type_traits> #include <limits> #include <QMetaType> #include <QString> #include <pcl/point_cloud.h> #include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include <pcl/common/centroid.h> #include <pcl/common/common.h> #include <pcl/common/distances.h> #include <pcl/visualization/pcl_visualizer.h> #include <vtkCamera.h> #include <vtkMath.h> #include <vtkTransform.h> #include <QMutex> #include <QMessageBox> #include <QPushButton> #include <QThread> #include <QMap> #include <QTime> #include <memory> #include <QSharedPointer> #include <QtMath> #ifndef M_PI_2_3 #define M_PI_2_3 (2 * M_PI / 3) #endif namespace Gui { namespace common { template <typename T> typename std::enable_if_t<std::is_floating_point_v<T>, bool> is_zero(T value, T epsilon = std::numeric_limits<T>::epsilon() * 100) { return std::abs(value) < epsilon; } template <typename T> typename std::enable_if_t<std::is_floating_point_v<T>, bool> is_non_zero(T value, T epsilon = std::numeric_limits<T>::epsilon() * 100) { return !is_zero(value, epsilon); } // 角度转弧度 inline double deg2rad(double deg) { return deg * (M_PI / 180.0); } // 弧度转角度 inline double rad2deg(double rad) { return rad * (180.0 / M_PI); } /** * @brief getXORSumByByte 按字节求字节数组的所有元素的异或和 * @param data * @param size * @return */ char getXORSumByByte(const char* data, unsigned int size); /** * @brief The Singleton class 模板单例类,继承该类即可实现单例 */ template<typename T> class Singleton : public QObject { public: static T& instance() { static std::unique_ptr<T> instance; static QMutex mutex; if (!instance) { QMutexLocker locker(&mutex); if (!instance) { instance.reset(new T()); } } return *instance; } protected: Singleton() = default; virtual ~Singleton() = default; // 禁止拷贝 Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; }; int calReMainingTime(const QTime& curTime, const QTime& targetTime); } namespace Ctl { namespace rtsp { const int RTSP_STOP = 0x1; const int RTSP_CONTINU = 0x2; const int RTSP_OPENED = 0x3; // 错误状态以0x10开始 const int RTSP_NETWORK_ERROR = 0x10; const int RTSP_NOT_GET_INFO = 0x11; const int RTSP_NOT_FOUND = 0x12; const int RTSP_NOT_FOUND_DECODER = 0x13; const int RTSP_NOT_CREATE_DECODER_CONTEXT = 0x14; const int RTSP_NOT_OPEN_DECODER = 0x15; const int RTSP_NOT_ALLOCK_FRAME = 0x16; const int RTSP_FAULT = 0x17; } } 注释上述代码
09-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangzhangkeji

谢谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值