东营外贸型网站设计,模板制作工艺流程,建设银行银行官网网站,wordpress本地环境404简介
在多线程中往往需要访问临界资源#xff0c;C11为我们提供了mutex等相关类来保护临界资源#xff0c;保证某一时刻只有一个线程可以访问临界资源。主要包括各种mutex#xff0c;他们的命名大都是xx_mutex。以及RAII风格的wrapper类#xff0c;RAII就是一般在构造的时…简介
在多线程中往往需要访问临界资源C11为我们提供了mutex等相关类来保护临界资源保证某一时刻只有一个线程可以访问临界资源。主要包括各种mutex他们的命名大都是xx_mutex。以及RAII风格的wrapper类RAII就是一般在构造的时候上锁在析构的时候解锁。
C11提供的锁类型有三个
mutex头文件timed_mutex头文件recursive_mutex头文件recursive_timed_mutex头文件shared_mutex
C11提供的RAII风格的wrapper类有两个
lock_guard头文件unique_lock头文件
std::mutex
mutex提供的方法不过主要有lock和unlock mutex只有默认构造方法不允许拷贝构造目前也没有提供移动构造
constexpr mutex() noexcept;
mutex( const mutex ) delete;lock和try_lock的区别是lock会阻塞当前线程而try_lock不会如果没有获取到锁则返回false如果获取到则返回true。
std::timed_mutex
相比于mutextimed_mutex多了try_lock_for和try_lock_until两个方法。try_lock_for表示花多长时间尝试获取锁如果超过时长则失败。try_lock_until表示尝试获取锁到什么时候如果超过指定时间点则失败。
try_lock_for的函数声明如下两个模板参数都是形参timeout_duration的Rep表示保存时间段的类型Period表示单位比如秒毫秒等。详细参考chrono。try_lock_for表达的意思就是阻塞获取锁最长阻塞timeout_duration时间。如果期间获取到了锁则返回true否则返回false。如果timeout_duration小于等于0try_lock_for的行为就和try_lock一样。
template class Rep, class Period
bool try_lock_for( const std::chrono::durationRep, Period timeout_duration );例子
#include iostream
#include thread
#include mutex
#include chronovoid run(std::timed_mutex mutex)
{if (mutex.try_lock_for(std::chrono::milliseconds(500))) {std::cout 获得了锁 std::endl;} else {std::cout 未获得锁 std::endl;}
}int main() {std::timed_mutex mutex;mutex.lock();std::thread thread(run, std::ref(mutex));thread.join();mutex.unlock();return 0;
}//输出未获得锁try_lock_until的函数声明如下两个模板参数都是形参timeout_time的Clock是始终类型Duration就是前面的std::chrono::duration。try_lock_until表达的意识就是阻塞获取锁一直阻塞到timeout_time这个时间点。如果期间获取到了锁则返回true否则返回false。time_point 参考。
template class Clock, class Duration
bool try_lock_until( const std::chrono::time_pointClock, Duration timeout_time );例子
#include iostream
#include thread
#include mutex
#include chronovoid run(std::timed_mutex mutex)
{std::chrono::time_pointstd::chrono::system_clock now std::chrono::system_clock::now();if (mutex.try_lock_for(now std::chrono::milliseconds(500))) {std::cout 获得了锁 std::endl;} else {std::cout 未获得锁 std::endl;}
}int main() {std::timed_mutex mutex;mutex.lock();std::thread thread(run, std::ref(mutex));thread.join();mutex.unlock();return 0;
}//输出未获得锁std::recursive_mutex
recursive_mutex和mutex的区别就在“recursive“recursive_mutex允许同一个线程多次lock当然需要相同次数的unlock。c没有规定最多可以调用多少次如果到达了最大lock次数lock方法会抛出异常std::system_errortry_lock会返回false。
std::recursive_timed_mutex
recursive_timed_mutex就是recursive_mutex和timed_mutex的结合体提供的方法如下
std::lock_guard
lock_guard是一个RAII风格mutex wrapper即就是在他析构的时候会解锁他关联的mutex。一般在构造lock_guard的时候给mutex上锁当然也有例外具体得看在调用lock_guard的构造方法时传的参数。 下面是lock_guard提供的方法 构造方法可用的有两个
explicit lock_guard( mutex_type m ); // 在构造lock_guard的时候调用m的lock方法在析构的时候调用m的unlock方法
lock_guard( mutex_type m, std::adopt_lock_t t ); // 只是关联m但是不调用m的lock方法在析构的时候调用m的unlock方法
lock_guard( const lock_guard ) delete; // 禁止拷贝构造lock_guardstd::unique_lock
相比于lock_guardunique_lock提供了更强大的功能虽然不能拷贝但是可以移动。处理支持mutex的所有操作外还可以支持mutex延迟上锁尝试上锁等。lock_guard提供的方法有 unique_lock提供的构造方法比较多
unique_lock() noexcept; // 构造一个不关联mutex的unique_lock对象他可以通过移动拷贝操作符关联到一个mutex或者调用swap方法
unique_lock( unique_lock other ) noexcept; // 移动构造
explicit unique_lock( mutex_type m ); // 构造unique_lock的时候调用m.lock()
unique_lock( mutex_type m, std::defer_lock_t t ) noexcept; // 仅关联m但是不调用m的lock方法
// 关联m并且调用m的try_lock方法当然前提是m有try_lock方法如果没有则行为是未定义的。
// try_lock可能失败返回false。unique_lock的构造方法没有返回值我们怎么知道m有没有上锁成功。
// 调用unique_lock的owns_lock方法他返回bool可以知道m有没有上锁成功。具体可以参考例子
unique_lock( mutex_type m, std::try_to_lock_t t );
// 关联已经上锁的m如果m没有上锁则行为未定义
unique_lock( mutex_type m, std::adopt_lock_t t );// 构造unique_lock的时候关联m并且执行m.try_lock_for(timeout_duration)。
// m上锁有没有成功仍然可以通过unique_lock的owns_lock方法获取
template class Rep, class Period
unique_lock( mutex_type m, const std::chrono::durationRep, Period timeout_duration );// 和上一个方法类似只不过执行的是m.try_lock_until(timeout_time)
template class Clock, class Duration
unique_lock( mutex_type m, const std::chrono::time_pointClock, Duration timeout_time );try_to_lock的例子
#include iostream
#include mutexstd::mutex mtx;void fun() {std::unique_lockstd::mutex guard(mtx, std::try_to_lock);if (m_guard1.owns_lock()) {std::cout try_to_lock success std::endl;} else {std::cout try_to_lock failed std::endl;}
}当unique_lock对象成功关联到了mutex并且他获得了锁则在析构的时候调用mutex的unlock方法。
unique_lock仅支持移动拷贝赋值操作符
unique_lock operator( unique_lock other );unique_lock还提供了获取mutex的方法在调用unique_lock提供的各种lock类方法时就如同mutex()-lock()
mutex_type* mutex() const noexcept;unique_lock还提供了unlock方法当调用这个方法的时候会调用mutex的unlock方法并且unique_lock释放mutex即不再关联当前mutex。当时当调用unlock方法时没有关联到mutex或者mutex没有获得锁则会抛出std::system_error异常。
void unlock();unique_lock的release方法只是与关联的mutex断开关联并不会调用mutex的unlock方法
mutex_type* release() noexcept;bool操作符相当于调用owns_lock()具体使用参考如下实例
explicit operator bool() const noexcept;#include iostream
#include mutex
#include threadclass Test {
public:void fun() {std::unique_lockstd::mutex lck(m_mtx);if (bool(lck)) {std::cout lock succ: bool(lck) std::endl;}if ((bool)lck) {std::cout lock succ: (bool)lck std::endl;}if (lck) {std::cout lock succ: lck std::endl;}}private:std::mutex m_mtx;
};int main() {Test test;std::thread thread(Test::fun, test);thread.join();return 0;
}/** 输出结果* lock succ: bool(lck)* lock succ: (bool)lck* lock succ: lck*/