求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   模型库  
会员   
 


DeepSeek大模型应用开发实践
6月12-13日 厦门



基于 UML 和EA进行分析设计
6月23-24日 北京+线上



人工智能、机器学习& TensorFlow+Keras
6月22-23日 北京
 
追随技术信仰

随时听讲座
每天看新闻
 
 
C++并发编程(中文版)
前言
第1章 你好,C++的并发世界!
1.1 何谓并发
1.2 为什么使用并发?
1.3 C++中的并发和多线程
1.4 开始入门
1.5 本章总结
第2章 线程管理
2.1 线程管理的基础
2.2 向线程函数传递参数
2.3 转移线程所有权
2.4 运行时决定线程数量
2.5 识别线程
2.6 本章总结
第3章 线程间共享数据
3.1 共享数据带来的问题
3.2 使用互斥量保护共享数据
3.3 保护共享数据的替代设施
3.4 本章总结
第4章 同步并发操作
4.1 等待一个事件或其他条件
4.2 使用期望等待一次性事件
4.3 限定等待时间
4.4 使用同步操作简化代码
4.5 本章总结
第5章 C++内存模型和原子类型操作
5.1 内存模型基础
5.2 C++中的原子操作和原子类型
5.3 同步操作和强制排序
5.4 本章总结
第6章 基于锁的并发数据结构设计
6.1 为并发设计的意义何在?
6.2 基于锁的并发数据结构
6.3 基于锁设计更加复杂的数据结构
6.4 本章总结
第7章 无锁并发数据结构设计
7.1 定义和意义
7.2 无锁数据结构的例子
7.3 对于设计无锁数据结构的指导建议
7.4 本章总结
第8章 并发代码设计
8.1 线程间划分工作的技术
8.2 影响并发代码性能的因素
8.3 为多线程性能设计数据结构
8.4 设计并发代码的注意事项
8.5 在实践中设计并发代码
8.6 本章总结
第9章 高级线程管理
9.1 线程池
9.2 中断线程
9.3 本章总结
第10章 多线程程序的测试和调试
10.1 与并发相关的错误类型
10.2 定位并发错误的技术
10.3 本章总结
附录A C++11语言特性简明参考(部分)
A .1 右值引用
A .2 删除函数
A .3 默认函数
A .4 常量表达式函数
A .5 Lambda函数
A .6 变参模板
A .7 自动推导变量类型
A .8 线程本地变量
A .9 本章总结
附录B 并发库的简单比较
附录C 消息传递框架与完整的ATM示例
 附录D C++线程库参考
D .1 chrono头文件
D .2 <condition_variable>头文件
D .3 <atomic>头文件
D .4 future头文件
D .5 <mutex>头文件
D .6 <ratio>头文件
D .7 <thread>头文件
 

 
目录
<mutex>头文件
作者:Anthony Williams  译者:陈晓伟
128 次浏览
13次  

D.5 <mutex>头文件

<mutex>头文件提供互斥工具:互斥类型,锁类型和函数,还有确保操作只执行一次的机制。

头文件内容

  1. namespace std
  2. {
  3. class mutex;
  4. class recursive_mutex;
  5. class timed_mutex;
  6. class recursive_timed_mutex;
  7. struct adopt_lock_t;
  8. struct defer_lock_t;
  9. struct try_to_lock_t;
  10. constexpr adopt_lock_t adopt_lock{};
  11. constexpr defer_lock_t defer_lock{};
  12. constexpr try_to_lock_t try_to_lock{};
  13. template<typename LockableType>
  14. class lock_guard;
  15. template<typename LockableType>
  16. class unique_lock;
  17. template<typename LockableType1,typename... LockableType2>
  18. void lock(LockableType1& m1,LockableType2& m2...);
  19. template<typename LockableType1,typename... LockableType2>
  20. int try_lock(LockableType1& m1,LockableType2& m2...);
  21. struct once_flag;
  22. template<typename Callable,typename... Args>
  23. void call_once(once_flag& flag,Callable func,Args args...);
  24. }

D.5.1 std::mutex类

std::mutex类型为线程提供基本的互斥和同步工具,这些工具可以用来保护共享数据。互斥量可以用来保护数据,互斥量上锁必须要调用lok()或try_lock()。当有一个线程获取已经获取了锁,那么其他线程想要在获取锁的时候,会在尝试或取锁的时候失败(调用try_lock())或阻塞(调用lock()),具体酌情而定。当线程完成对共享数据的访问,之后就必须调用unlock()对锁进行释放,并且允许其他线程来访问这个共享数据。

std::mutex符合Lockable的需求。

类型定义

  1. class mutex
  2. {
  3. public:
  4. mutex(mutex const&)=delete;
  5. mutex& operator=(mutex const&)=delete;
  6. constexpr mutex() noexcept;
  7. ~mutex();
  8. void lock();
  9. void unlock();
  10. bool try_lock();
  11. };

std::mutex 默认构造函数

构造一个std::mutex对象。

声明

constexpr mutex() noexcept;

效果

构造一个std::mutex实例。

后置条件

新构造的std::mutex对象是未锁的。

抛出

std::mutex 析构函数

销毁一个std::mutex对象。

声明

~mutex();

先决条件

*this必须是未锁的。

效果

销毁*this。

抛出

std::mutex::lock 成员函数

为当前线程获取std::mutex上的锁。

声明

void lock();

先决条件

*this上必须没有持有一个锁。

效果

阻塞当前线程,知道*this获取锁。

后置条件

*this被调用线程锁住。

抛出

当有错误产生,抛出std::system_error类型异常。

std::mutex::try_lock 成员函数

尝试为当前线程获取std::mutex上的锁。

声明

bool try_lock();

先决条件

*this上必须没有持有一个锁。

效果

尝试为当前线程*this获取上的锁,失败时当前线程不会被阻塞。

返回

当调用线程获取锁时,返回true。

后置条件

当*this被调用线程锁住,则返回true。

抛出

NOTE 该函数在获取锁时,可能失败(并返回false),即使没有其他线程持有*this上的锁。

std::mutex::unlock 成员函数

释放当前线程获取的std::mutex锁。

声明

void unlock();

 

先决条件

*this上必须持有一个锁。

效果

释放当前线程获取到*this上的锁。任意等待获取*this上的线程,会在该函数调用后解除阻塞。

后置条件

调用线程不在拥有*this上的锁。

抛出

D.5.2 std::recursive_mutex类

std::recursive_mutex类型为线程提供基本的互斥和同步工具,可以用来保护共享数据。互斥量可以用来保护数据,互斥量上锁必须要调用lok()或try_lock()。当有一个线程获取已经获取了锁,那么其他线程想要在获取锁的时候,会在尝试或取锁的时候失败(调用try_lock())或阻塞(调用lock()),具体酌情而定。当线程完成对共享数据的访问,之后就必须调用unlock()对锁进行释放,并且允许其他线程来访问这个共享数据。

这个互斥量是可递归的,所以一个线程获取std::recursive_mutex后可以在之后继续使用lock()或try_lock()来增加锁的计数。只有当线程调用unlock释放锁,其他线程才可能用lock()或try_lock()获取锁。

std::recursive_mutex符合Lockable的需求。

类型定义

  1. class recursive_mutex
  2. {
  3. public:
  4. recursive_mutex(recursive_mutex const&)=delete;
  5. recursive_mutex& operator=(recursive_mutex const&)=delete;
  6. recursive_mutex() noexcept;
  7. ~recursive_mutex();
  8. void lock();
  9. void unlock();
  10. bool try_lock() noexcept;
  11. };

std::recursive_mutex 默认构造函数

构造一个std::recursive_mutex对象。

声明

recursive_mutex() noexcept;

效果

构造一个std::recursive_mutex实例。

后置条件

新构造的std::recursive_mutex对象是未锁的。

抛出

当无法创建一个新的std::recursive_mutex时,抛出std::system_error异常。

std::recursive_mutex 析构函数

销毁一个std::recursive_mutex对象。

声明

~recursive_mutex();

先决条件

*this必须是未锁的。

效果

销毁*this。

抛出

std::recursive_mutex::lock 成员函数

为当前线程获取std::recursive_mutex上的锁。

声明

void lock();

效果

阻塞线程,直到获取*this上的锁。

先决条件

调用线程锁住this上的锁。当调用已经持有一个this的锁时,锁的计数会增加1。

抛出

当有错误产生,将抛出std::system_error异常。

std::recursive_mutex::try_lock 成员函数

尝试为当前线程获取std::recursive_mutex上的锁。

声明

bool try_lock() noexcept;

效果

尝试为当前线程*this获取上的锁,失败时当前线程不会被阻塞。

返回

当调用线程获取锁时,返回true;否则,返回false。

后置条件

当*this被调用线程锁住,则返回true。

抛出

NOTE 该函数在获取锁时,当函数返回true时,*this上对锁的计数会加一。如果当前线程还未获取*this上的锁,那么该函数在获取锁时,可能失败(并返回false),即使没有其他线程持有*this上的锁。

std::recursive_mutex::unlock 成员函数

释放当前线程获取的std::recursive_mutex锁。

声明

void unlock();

先决条件

*this上必须持有一个锁。

效果

释放当前线程获取到*this上的锁。如果这是*this在当前线程上最后一个锁,那么任意等待获取*this上的线程,会在该函数调用后解除其中一个线程的阻塞。

后置条件

*this上锁的计数会在该函数调用后减一。

抛出

D.5.3 std::timed_mutex类

std::timed_mutex类型在std::mutex基本互斥和同步工具的基础上,让锁支持超时。互斥量可以用来保护数据,互斥量上锁必须要调用lok(),try_lock_for(),或try_lock_until()。当有一个线程获取已经获取了锁,那么其他线程想要在获取锁的时候,会在尝试或取锁的时候失败(调用try_lock())或阻塞(调用lock()),或直到想要获取锁可以获取,亦或想要获取的锁超时(调用try_lock_for()或try_lock_until())。在线程调用unlock()对锁进行释放,其他线程才能获取这个锁被获取(不管是调用的哪个函数)。

std::timed_mutex符合TimedLockable的需求。

类型定义

  1. class timed_mutex
  2. {
  3. public:
  4. timed_mutex(timed_mutex const&)=delete;
  5. timed_mutex& operator=(timed_mutex const&)=delete;
  6. timed_mutex();
  7. ~timed_mutex();
  8. void lock();
  9. void unlock();
  10. bool try_lock();
  11. template<typename Rep,typename Period>
  12. bool try_lock_for(
  13. std::chrono::duration<Rep,Period> const& relative_time);
  14. template<typename Clock,typename Duration>
  15. bool try_lock_until(
  16. std::chrono::time_point<Clock,Duration> const& absolute_time);
  17. };

std::timed_mutex 默认构造函数

构造一个std::timed_mutex对象。

声明

timed_mutex();

效果

构造一个std::timed_mutex实例。

后置条件

新构造一个未上锁的std::timed_mutex对象。

抛出

当无法创建出新的std::timed_mutex实例时,抛出std::system_error类型异常。

std::timed_mutex 析构函数

销毁一个std::timed_mutex对象。

声明

~timed_mutex();

 

先决条件

*this必须没有上锁。

效果

销毁*this。

抛出

std::timed_mutex::lock 成员函数

为当前线程获取std::timed_mutex上的锁。

声明

void lock();

 

先决条件

调用线程不能已经持有*this上的锁。

效果

阻塞当前线程,直到获取到*this上的锁。

后置条件

*this被调用线程锁住。

抛出

当有错误产生,抛出std::system_error类型异常。

std::timed_mutex::try_lock 成员函数

尝试获取为当前线程获取std::timed_mutex上的锁。

声明

bool try_lock();

 

先决条件

调用线程不能已经持有*this上的锁。

效果

尝试获取*this上的锁,当获取失败时,不阻塞调用线程。

返回

当锁被调用线程获取,返回true;反之,返回false。

后置条件

当函数返回为true,*this则被当前线程锁住。

抛出

NOTE 即使没有线程已获取*this上的锁,函数还是有可能获取不到锁(并返回false)。

std::timed_mutex::try_lock_for 成员函数

尝试获取为当前线程获取std::timed_mutex上的锁。

声明

  1. template<typename Rep,typename Period>
  2. bool try_lock_for(
  3. std::chrono::duration<Rep,Period> const& relative_time);

先决条件

调用线程不能已经持有*this上的锁。

效果

在指定的relative_time时间内,尝试获取*this上的锁。当relative_time.count()为0或负数,将会立即返回,就像调用try_lock()一样。否则,将会阻塞,直到获取锁或超过给定的relative_time的时间。

返回

当锁被调用线程获取,返回true;反之,返回false。

后置条件

当函数返回为true,*this则被当前线程锁住。

抛出

NOTE 即使没有线程已获取*this上的锁,函数还是有可能获取不到锁(并返回false)。线程阻塞的时长可能会长于给定的时间。逝去的时间可能是由一个稳定时钟所决定。

std::timed_mutex::try_lock_until 成员函数

尝试获取为当前线程获取std::timed_mutex上的锁。

声明

  1. template<typename Clock,typename Duration>
  2. bool try_lock_until(
  3. std::chrono::time_point<Clock,Duration> const& absolute_time);

先决条件

调用线程不能已经持有*this上的锁。

效果

在指定的absolute_time时间内,尝试获取*this上的锁。当absolute_time<=Clock::now()时,将会立即返回,就像调用try_lock()一样。否则,将会阻塞,直到获取锁或Clock::now()返回的时间等于或超过给定的absolute_time的时间。

返回

当锁被调用线程获取,返回true;反之,返回false。

后置条件

当函数返回为true,*this则被当前线程锁住。

抛出

NOTE 即使没有线程已获取*this上的锁,函数还是有可能获取不到锁(并返回false)。这里不保证调用函数要阻塞多久,只有在函数返回false后,在Clock::now()返回的时间大于或等于absolute_time时,线程才会接触阻塞。

std::timed_mutex::unlock 成员函数

将当前线程持有std::timed_mutex对象上的锁进行释放。

声明

void unlock();

先决条件

调用线程已经持有*this上的锁。

效果

当前线程释放*this上的锁。任一阻塞等待获取*this上的线程,将被解除阻塞。

后置条件

*this未被调用线程上锁。

抛出

D.5.4 std::recursive_timed_mutex类

std::recursive_timed_mutex类型在std::recursive_mutex提供的互斥和同步工具的基础上,让锁支持超时。互斥量可以用来保护数据,互斥量上锁必须要调用lok(),try_lock_for(),或try_lock_until()。当有一个线程获取已经获取了锁,那么其他线程想要在获取锁的时候,会在尝试或取锁的时候失败(调用try_lock())或阻塞(调用lock()),或直到想要获取锁可以获取,亦或想要获取的锁超时(调用try_lock_for()或try_lock_until())。在线程调用unlock()对锁进行释放,其他线程才能获取这个锁被获取(不管是调用的哪个函数)。

该互斥量是可递归的,所以获取std::recursive_timed_mutex锁的线程,可以多次的对该实例上的锁获取。所有的锁将会在调用相关unlock()操作后,可由其他线程获取该实例上的锁。

std::recursive_timed_mutex符合TimedLockable的需求。

类型定义

  1. class recursive_timed_mutex
  2. {
  3. public:
  4. recursive_timed_mutex(recursive_timed_mutex const&)=delete;
  5. recursive_timed_mutex& operator=(recursive_timed_mutex const&)=delete;
  6. recursive_timed_mutex();
  7. ~recursive_timed_mutex();
  8. void lock();
  9. void unlock();
  10. bool try_lock() noexcept;
  11. template<typename Rep,typename Period>
  12. bool try_lock_for(
  13. std::chrono::duration<Rep,Period> const& relative_time);
  14. template<typename Clock,typename Duration>
  15. bool try_lock_until(
  16. std::chrono::time_point<Clock,Duration> const& absolute_time);
  17. };

std::recursive_timed_mutex 默认构造函数

构造一个std::recursive_timed_mutex对象。

声明

recursive_timed_mutex();

效果

构造一个std::recursive_timed_mutex实例。

后置条件

新构造的std::recursive_timed_mutex实例是没有上锁的。

抛出

当无法创建一个std::recursive_timed_mutex实例时,抛出std::system_error类异常。

std::recursive_timed_mutex 析构函数

析构一个std::recursive_timed_mutex对象。

声明

~recursive_timed_mutex();

先决条件

*this不能上锁。

效果

销毁*this。

抛出

std::recursive_timed_mutex::lock 成员函数

为当前线程获取std::recursive_timed_mutex对象上的锁。

声明

void lock();

先决条件

*this上的锁不能被线程调用。

效果

阻塞当前线程,直到获取*this上的锁。

后置条件

*this被调用线程锁住。当调用线程已经获取*this上的锁,那么锁的计数会再增加1。

抛出

当错误出现时,抛出std::system_error类型异常。

std::recursive_timed_mutex::try_lock 成员函数

尝试为当前线程获取std::recursive_timed_mutex对象上的锁。

声明

bool try_lock() noexcept;

效果

尝试获取*this上的锁,当获取失败时,直接不阻塞线程。

返回

当调用线程获取了锁,返回true,否则返回false。

后置条件

当函数返回true,*this会被调用线程锁住。

抛出

NOTE 该函数在获取锁时,当函数返回true时,*this上对锁的计数会加一。如果当前线程还未获取*this上的锁,那么该函数在获取锁时,可能失败(并返回false),即使没有其他线程持有*this上的锁。

std::recursive_timed_mutex::try_lock_for 成员函数

尝试为当前线程获取std::recursive_timed_mutex对象上的锁。

声明

  1. template<typename Rep,typename Period>
  2. bool try_lock_for(
  3. std::chrono::duration<Rep,Period> const& relative_time);

效果

在指定时间relative_time内,尝试为调用线程获取*this上的锁。当relative_time.count()为0或负数时,将会立即返回,就像调用try_lock()一样。否则,调用会阻塞,直到获取相应的锁,或超出了relative_time时限时,调用线程解除阻塞。

返回

当调用线程获取了锁,返回true,否则返回false。

后置条件

当函数返回true,*this会被调用线程锁住。

抛出

NOTE 该函数在获取锁时,当函数返回true时,*this上对锁的计数会加一。如果当前线程还未获取*this上的锁,那么该函数在获取锁时,可能失败(并返回false),即使没有其他线程持有*this上的锁。等待时间可能要比指定的时间长很多。逝去的时间可能由一个稳定时钟来计算。

std::recursive_timed_mutex::try_lock_until 成员函数

尝试为当前线程获取std::recursive_timed_mutex对象上的锁。

声明

  1. template<typename Clock,typename Duration>
  2. bool try_lock_until(
  3. std::chrono::time_point<Clock,Duration> const& absolute_time);

效果

在指定时间absolute_time内,尝试为调用线程获取*this上的锁。当absolute_time<=Clock::now()时,将会立即返回,就像调用try_lock()一样。否则,调用会阻塞,直到获取相应的锁,或Clock::now()返回的时间大于或等于absolute_time时,调用线程解除阻塞。

返回

当调用线程获取了锁,返回true,否则返回false。

后置条件

当函数返回true,*this会被调用线程锁住。

抛出

NOTE 该函数在获取锁时,当函数返回true时,*this上对锁的计数会加一。如果当前线程还未获取*this上的锁,那么该函数在获取锁时,可能失败(并返回false),即使没有其他线程持有*this上的锁。这里阻塞的时间并不确定,只有当函数返回false,然后Clock::now()返回的时间大于或等于absolute_time时,调用线程将会解除阻塞。

std::recursive_timed_mutex::unlock 成员函数

释放当前线程获取到的std::recursive_timed_mutex上的锁。

声明

void unlock();

效果

当前线程释放*this上的锁。当*this上最后一个锁被释放后,任何等待获取*this上的锁将会解除阻塞,不过只能解除其中一个线程的阻塞。

后置条件

调用线程*this上锁的计数减一。

抛出

D.5.5 std::lock_guard类型模板

std::lock_guard类型模板为基础锁包装所有权。所要上锁的互斥量类型,由模板参数Mutex来决定,并且必须符合Lockable的需求。指定的互斥量在构造函数中上锁,在析构函数中解锁。这就为互斥量锁部分代码提供了一个简单的方式;当程序运行完成时,阻塞解除,互斥量解锁(无论是执行到最后,还是通过控制流语句break或return,亦或是抛出异常)。

std::lock_guard是不可MoveConstructible(移动构造), CopyConstructible(拷贝构造)和CopyAssignable(拷贝赋值)。

类型定义

  1. template <class Mutex>
  2. class lock_guard
  3. {
  4. public:
  5. typedef Mutex mutex_type;
  6. explicit lock_guard(mutex_type& m);
  7. lock_guard(mutex_type& m, adopt_lock_t);
  8. ~lock_guard();
  9. lock_guard(lock_guard const& ) = delete;
  10. lock_guard& operator=(lock_guard const& ) = delete;
  11. };

std::lock_guard 自动上锁的构造函数

使用互斥量构造一个std::lock_guard实例。

声明

explicit lock_guard(mutex_type& m);

效果

通过引用提供的互斥量,构造一个新的std::lock_guard实例,并调用m.lock()。

抛出

m.lock()抛出的任何异常。

后置条件

*this拥有m上的锁。

std::lock_guard 获取锁的构造函数

使用已提供互斥量上的锁,构造一个std::lock_guard实例。

声明

lock_guard(mutex_type& m,std::adopt_lock_t);

先决条件

调用线程必须拥有m上的锁。

效果

调用线程通过引用提供的互斥量,以及获取m上锁的所有权,来构造一个新的std::lock_guard实例。

抛出

后置条件

*this拥有m上的锁。

std::lock_guard 析构函数

销毁一个std::lock_guard实例,并且解锁相关互斥量。

声明

~lock_guard();

效果

当*this被创建后,调用m.unlock()。

抛出

D.5.6 std::unique_lock类型模板

std::unique_lock类型模板相较std::loc_guard提供了更通用的所有权包装器。上锁的互斥量可由模板参数Mutex提供,这个类型必须满足BasicLockable的需求。虽然,通常情况下,制定的互斥量会在构造的时候上锁,析构的时候解锁,但是附加的构造函数和成员函数提供灵活的功能。互斥量上锁,意味着对操作同一段代码的线程进行阻塞;当互斥量解锁,就意味着阻塞解除(不论是裕兴到最后,还是使用控制语句break和return,亦或是抛出异常)。std::condition_variable的邓丹函数是需要std::unique_lock<std::mutex>实例的,并且所有std::unique_lock实例都适用于std::conditin_variable_any等待函数的Lockable参数。

当提供的Mutex类型符合Lockable的需求,那么std::unique_lock<Mutex>也是符合Lockable的需求。此外,如果提供的Mutex类型符合TimedLockable的需求,那么std::unique_lock<Mutex>也符合TimedLockable的需求。

std::unique_lock实例是MoveConstructible(移动构造)和MoveAssignable(移动赋值),但是不能CopyConstructible(拷贝构造)和CopyAssignable(拷贝赋值)。

类型定义

  1. template <class Mutex>
  2. class unique_lock
  3. {
  4. public:
  5. typedef Mutex mutex_type;
  6. unique_lock() noexcept;
  7. explicit unique_lock(mutex_type& m);
  8. unique_lock(mutex_type& m, adopt_lock_t);
  9. unique_lock(mutex_type& m, defer_lock_t) noexcept;
  10. unique_lock(mutex_type& m, try_to_lock_t);
  11. template<typename Clock,typename Duration>
  12. unique_lock(
  13. mutex_type& m,
  14. std::chrono::time_point<Clock,Duration> const& absolute_time);
  15. template<typename Rep,typename Period>
  16. unique_lock(
  17. mutex_type& m,
  18. std::chrono::duration<Rep,Period> const& relative_time);
  19. ~unique_lock();
  20. unique_lock(unique_lock const& ) = delete;
  21. unique_lock& operator=(unique_lock const& ) = delete;
  22. unique_lock(unique_lock&& );
  23. unique_lock& operator=(unique_lock&& );
  24. void swap(unique_lock& other) noexcept;
  25. void lock();
  26. bool try_lock();
  27. template<typename Rep, typename Period>
  28. bool try_lock_for(
  29. std::chrono::duration<Rep,Period> const& relative_time);
  30. template<typename Clock, typename Duration>
  31. bool try_lock_until(
  32. std::chrono::time_point<Clock,Duration> const& absolute_time);
  33. void unlock();
  34. explicit operator bool() const noexcept;
  35. bool owns_lock() const noexcept;
  36. Mutex* mutex() const noexcept;
  37. Mutex* release() noexcept;
  38. };

std::unique_lock 默认构造函数

不使用相关互斥量,构造一个std::unique_lock实例。

声明

unique_lock() noexcept;

效果

构造一个std::unique_lock实例,这个新构造的实例没有相关互斥量。

后置条件

this->mutex()==NULL, this->owns_lock()==false.

std::unique_lock 自动上锁的构造函数

使用相关互斥量,构造一个std::unique_lock实例。

声明

explicit unique_lock(mutex_type& m);

 

效果

通过提供的互斥量,构造一个std::unique_lock实例,且调用m.lock()。

抛出

m.lock()抛出的任何异常。

后置条件

this->owns_lock()==true, this->mutex()==&m.

std::unique_lock 获取锁的构造函数

使用相关互斥量和持有的锁,构造一个std::unique_lock实例。

声明

unique_lock(mutex_type& m,std::adopt_lock_t);

先决条件

调用线程必须持有m上的锁。

效果

通过提供的互斥量和已经拥有m上的锁,构造一个std::unique_lock实例。

抛出

后置条件

this->owns_lock()==true, this->mutex()==&m.

std::unique_lock 递延锁的构造函数

使用相关互斥量和非持有的锁,构造一个std::unique_lock实例。

声明

unique_lock(mutex_type& m,std::defer_lock_t) noexcept;

效果

构造的std::unique_lock实例引用了提供的互斥量。

抛出

后置条件

this->owns_lock()==false, this->mutex()==&m.

std::unique_lock 尝试获取锁的构造函数

使用提供的互斥量,并尝试从互斥量上获取锁,从而构造一个std::unique_lock实例。

声明

unique_lock(mutex_type& m,std::try_to_lock_t);

先决条件

使std::unique_lock实例化的Mutex类型,必须符合Loackable的需求。

效果

构造的std::unique_lock实例引用了提供的互斥量,且调用m.try_lock()。

抛出

后置条件

this->owns_lock()将返回m.try_lock()的结果,且this->mutex()==&m。

std::unique_lock 在给定时长内尝试获取锁的构造函数

使用提供的互斥量,并尝试从互斥量上获取锁,从而构造一个std::unique_lock实例。

声明

  1. template<typename Rep,typename Period>
  2. unique_lock(
  3. mutex_type& m,
  4. std::chrono::duration<Rep,Period> const& relative_time);

先决条件

使std::unique_lock实例化的Mutex类型,必须符合TimedLockable的需求。

效果

构造的std::unique_lock实例引用了提供的互斥量,且调用m.try_lock_for(relative_time)。

抛出

后置条件

this->owns_lock()将返回m.try_lock_for()的结果,且this->mutex()==&m。

std::unique_lock 在给定时间点内尝试获取锁的构造函数

使用提供的互斥量,并尝试从互斥量上获取锁,从而构造一个std::unique_lock实例。

声明

  1. template<typename Clock,typename Duration>
  2. unique_lock(
  3. mutex_type& m,
  4. std::chrono::time_point<Clock,Duration> const& absolute_time);

先决条件

使std::unique_lock实例化的Mutex类型,必须符合TimedLockable的需求。

效果

构造的std::unique_lock实例引用了提供的互斥量,且调用m.try_lock_until(absolute_time)。

抛出

后置条件

this->owns_lock()将返回m.try_lock_until()的结果,且this->mutex()==&m。

std::unique_lock 移动构造函数

将一个已经构造std::unique_lock实例的所有权,转移到新的std::unique_lock实例上去。

声明

unique_lock(unique_lock&& other) noexcept;

先决条件

使std::unique_lock实例化的Mutex类型,必须符合TimedLockable的需求。

效果

构造的std::unique_lock实例。当other在函数调用的时候拥有互斥量上的锁,那么该锁的所有权将被转移到新构建的std::unique_lock对象当中去。

后置条件

对于新构建的std::unique_lock对象x,x.mutex等价与在构造函数调用前的other.mutex(),并且x.owns_lock()等价于函数调用前的other.owns_lock()。在调用函数后,other.mutex()==NULL,other.owns_lock()=false。

抛出

NOTE std::unique_lock对象是不可CopyConstructible(拷贝构造),所以这里没有拷贝构造函数,只有移动构造函数。

std::unique_lock 移动赋值操作

将一个已经构造std::unique_lock实例的所有权,转移到新的std::unique_lock实例上去。

声明

unique_lock& operator=(unique_lock&& other) noexcept;

效果

当this->owns_lock()返回true时,调用this->unlock()。如果other拥有mutex上的锁,那么这个所将归*this所有。

后置条件

this->mutex()等于在为进行赋值前的other.mutex(),并且this->owns_lock()的值与进行赋值操作前的other.owns_lock()相等。other.mutex()==NULL, other.owns_lock()==false。

抛出

NOTE std::unique_lock对象是不可CopyAssignable(拷贝赋值),所以这里没有拷贝赋值函数,只有移动赋值函数。

std::unique_lock 析构函数

销毁一个std::unique_lock实例,如果该实例拥有锁,那么会将相关互斥量进行解锁。

声明

~unique_lock();

效果

当this->owns_lock()返回true时,调用this->mutex()->unlock()。

抛出

std::unique_lock::swap 成员函数

交换std::unique_lock实例中相关的所有权。

声明

void swap(unique_lock& other) noexcept;

 

效果

如果other在调用该函数前拥有互斥量上的锁,那么这个锁将归*this所有。如果*this在调用哎函数前拥有互斥量上的锁,那么这个锁将归other所有。

抛出

std::unique_lock 上非成员函数swap

交换std::unique_lock实例中相关的所有权。

声明

void swap(unique_lock& lhs,unique_lock& rhs) noexcept;

 

效果

lhs.swap(rhs)

 

抛出

std::unique_lock::lock 成员函数

获取与*this相关互斥量上的锁。

声明

void lock();

 

先决条件

this->mutex()!=NULL, this->owns_lock()==false.

 

效果

调用this->mutex()->lock()。

抛出

抛出任何this->mutex()->lock()所抛出的异常。当this->mutex()==NULL,抛出std::sytem_error类型异常,错误码为std::errc::operation_not_permitted。当this->owns_lock()==true时,抛出std::system_error,错误码为std::errc::resource_deadlock_would_occur。

后置条件

this->owns_lock()==true。

std::unique_lock::try_lock 成员函数

尝试获取与*this相关互斥量上的锁。

声明

bool try_lock();

 

先决条件

std::unique_lock实例化说是用的Mutex类型,必须满足Lockable需求。this->mutex()!=NULL, this->owns_lock()==false。

效果

调用this->mutex()->try_lock()。

抛出

抛出任何this->mutex()->try_lock()所抛出的异常。当this->mutex()==NULL,抛出std::sytem_error类型异常,错误码为std::errc::operation_not_permitted。当this->owns_lock()==true时,抛出std::system_error,错误码为std::errc::resource_deadlock_would_occur。

后置条件

当函数返回true时,this->ows_lock()==true,否则this->owns_lock()==false。

std::unique_lock::unlock 成员函数

释放与*this相关互斥量上的锁。

声明

void unlock();

 

先决条件

this->mutex()!=NULL, this->owns_lock()==true。

抛出

抛出任何this->mutex()->unlock()所抛出的异常。当this->owns_lock()==false时,抛出std::system_error,错误码为std::errc::operation_not_permitted。

后置条件

this->owns_lock()==false。

std::unique_lock::try_lock_for 成员函数

在指定时间内尝试获取与*this相关互斥量上的锁。

声明

  1. template<typename Rep, typename Period>
  2. bool try_lock_for(
  3. std::chrono::duration<Rep,Period> const& relative_time);

先决条件

std::unique_lock实例化说是用的Mutex类型,必须满足TimedLockable需求。this->mutex()!=NULL, this->owns_lock()==false。

效果

调用this->mutex()->try_lock_for(relative_time)。

返回

当this->mutex()->try_lock_for()返回true,返回true,否则返回false。

抛出

抛出任何this->mutex()->try_lock_for()所抛出的异常。当this->mutex()==NULL,抛出std::sytem_error类型异常,错误码为std::errc::operation_not_permitted。当this->owns_lock()==true时,抛出std::system_error,错误码为std::errc::resource_deadlock_would_occur。

后置条件

当函数返回true时,this->ows_lock()==true,否则this->owns_lock()==false。

std::unique_lock::try_lock_until 成员函数

在指定时间点尝试获取与*this相关互斥量上的锁。

声明

  1. template<typename Clock, typename Duration>
  2. bool try_lock_until(
  3. std::chrono::time_point<Clock,Duration> const& absolute_time);

先决条件

std::unique_lock实例化说是用的Mutex类型,必须满足TimedLockable需求。this->mutex()!=NULL, this->owns_lock()==false。

效果

调用this->mutex()->try_lock_until(absolute_time)。

返回

当this->mutex()->try_lock_for()返回true,返回true,否则返回false。

抛出

抛出任何this->mutex()->try_lock_for()所抛出的异常。当this->mutex()==NULL,抛出std::sytem_error类型异常,错误码为std::errc::operation_not_permitted。当this->owns_lock()==true时,抛出std::system_error,错误码为std::errc::resource_deadlock_would_occur。

后置条件

当函数返回true时,this->ows_lock()==true,否则this->owns_lock()==false。

std::unique_lock::operator bool成员函数

检查*this是否拥有一个互斥量上的锁。

声明

explicit operator bool() const noexcept;

返回

this->owns_lock()

抛出

NOTE 这是一个explicit转换操作,所以当这样的操作在上下文中只能被隐式的调用,所返回的结果需要被当做一个布尔量进行使用,而非仅仅作为整型数0或1。

std::unique_lock::owns_lock 成员函数

检查*this是否拥有一个互斥量上的锁。

声明

bool owns_lock() const noexcept;

返回

当*this持有一个互斥量的锁,返回true;否则,返回false。

抛出

std::unique_lock::mutex 成员函数

当*this具有相关互斥量时,返回这个互斥量

声明

mutex_type* mutex() const noexcept;

 

返回

当*this有相关互斥量,则返回该互斥量;否则,返回NULL。

抛出

std::unique_lock::release 成员函数

当*this具有相关互斥量时,返回这个互斥量,并将这个互斥量进行释放。

声明

mutex_type* release() noexcept;

 

效果

将*this与相关的互斥量之间的关系解除,同时解除所有持有锁的所有权。

返回

返回与*this相关的互斥量指针,如果没有相关的互斥量,则返回NULL。

后置条件

this->mutex()==NULL, this->owns_lock()==false。

抛出

NOTE 如果this->owns_lock()在调用该函数前返回true,那么调用者则有责任里解除互斥量上的锁。

D.5.7 std::lock函数模板

std::lock函数模板提供同时锁住多个互斥量的功能,且不会有因改变锁的一致性而导致的死锁。

声明

  1. template<typename LockableType1,typename... LockableType2>
  2. void lock(LockableType1& m1,LockableType2& m2...);

先决条件

提供的可锁对象LockableType1, LockableType2…,需要满足Lockable的需求。

效果

使用未指定顺序调用lock(),try_lock()获取每个可锁对象(m1, m2…)上的锁,还有unlock()成员来避免这个类型陷入死锁。

后置条件

当前线程拥有提供的所有可锁对象上的锁。

抛出

任何lock(), try_lock()和unlock()抛出的异常。

NOTE 如果一个异常由std::lock所传播开来,当可锁对象上有锁被lock()或try_lock()获取,那么unlock()会使用在这些可锁对象上。

D.5.8 std::try_lock函数模板

std::try_lock函数模板允许尝试获取一组可锁对象上的锁,所以要不全部获取,要不一个都不获取。

声明

  1. template<typename LockableType1,typename... LockableType2>
  2. int try_lock(LockableType1& m1,LockableType2& m2...);

先决条件

提供的可锁对象LockableType1, LockableType2…,需要满足Lockable的需求。

效果

使用try_lock()尝试从提供的可锁对象m1,m2…上逐个获取锁。当锁在之前获取过,但被当前线程使用unlock()对相关可锁对象进行了释放后,try_lock()会返回false或抛出一个异常。

返回

当所有锁都已获取(每个互斥量调用try_lock()返回true),则返回-1,否则返回以0为基数的数字,其值为调用try_lock()返回false的个数。

后置条件

当函数返回-1,当前线程获取从每个可锁对象上都获取一个锁。否则,通过该调用获取的任何锁都将被释放。

抛出

try_lock()抛出的任何异常。

NOTE 如果一个异常由std::try_lock所传播开来,则通过try_lock()获取锁对象,将会调用unlock()解除对锁的持有。

D.5.9 std::once_flag类

std::once_flag和std::call_once一起使用,为了保证某特定函数只执行一次(即使有多个线程在并发的调用该函数)。

std::once_flag实例是不能CopyConstructible(拷贝构造),CopyAssignable(拷贝赋值),MoveConstructible(移动构造),以及MoveAssignable(移动赋值)。

类型定义

  1. struct once_flag
  2. {
  3. constexpr once_flag() noexcept;
  4. once_flag(once_flag const& ) = delete;
  5. once_flag& operator=(once_flag const& ) = delete;
  6. };

std::once_flag 默认构造函数

std::once_flag默认构造函数创建了一个新的std::once_flag实例(并包含一个状态,这个状态表示相关函数没有被调用)。

声明

constexpr once_flag() noexcept;

 

效果

std::once_flag默认构造函数创建了一个新的std::once_flag实例(并包含一个状态,这个状态表示相关函数没有被调用)。因为这是一个constexpr构造函数,在构造的静态初始部分,实例是静态存储的,这样就避免了条件竞争和初始化顺序的问题。

D.5.10 std::call_once函数模板

std::call_once和std::once_flag一起使用,为了保证某特定函数只执行一次(即使有多个线程在并发的调用该函数)。

声明

  1. template<typename Callable,typename... Args>
  2. void call_once(std::once_flag& flag,Callable func,Args args...);

先决条件

表达式INVOKE(func,args)提供的func和args必须是合法的。Callable和每个Args的成员都是可MoveConstructible(移动构造)。

效果

在同一个std::once_flag对象上调用std::call_once是串行的。如果之前没有在同一个std::once_flag对象上调用过std::call_once,参数func(或副本)被调用,就像INVOKE(func, args),并且只有可调用的func不抛出任何异常时,调用std::call_once才是有效的。当有异常抛出,异常会被调用函数进行传播。如果之前在std::once_flag上的std::call_once是有效的,那么再次调用std::call_once将不会在调用func。

同步

在std::once_flag上完成对std::call_once的调用的先决条件是,后续所有对std::call_once调用都在同一std::once_flag对象。

抛出

当效果没有达到,或任何异常由调用func而传播,则抛出std::system_error。

 

 


您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码: 验证码,看不清楚?请点击刷新验证码 必填



128 次浏览
13次