mutex 类
详细方法介绍参见C++ Ref
-
Mutex Types
Mutex types是lockable type类型,用于保护对特定区域代码的访问。支持操作:lock 和unlock。lock操作用于防止其他thread的访问,unlock操作用于解除lock。C++11中有4种Mutex Type
- mutex
-
- 构造器 constexpr mutex() noexcept; 不支持拷贝构造或者赋值构造
-
- 支持lock(),try_lock(),unlock(),native_handle()方法
- recursive_mutex
-
- 与mutex相比,其lock()与try_lock()可以对同一recursive_mutex对象获得多级ownership
- timed_mutex
-
- 额外提供try_lock_for()与try_lock_until()方法。两个方法的含义是在timed_mutex对象被其他线程lock住时,当前线程将会block for duration or to timepoint
- recursive_timed_mutex 集成了recursive_mutex和timed_mutex特性
lock方法执行区别
- 对任意的mutex type对象,若其(cur_mutex)已被其他thread locked,则调用lock()方法将会进入block,调用try_lock()方法将会失败,返回false;调用try_lock_for/try_lock_until()方法将会block一段时间,在此期间一直等待获取cur_mutex的lock
- 若cur_mutex还没有被任意thread获取lock,则所有lock方法将会获得lock并返回
- 若cur_mutex已被当前thread获取lock,对于mutex对象和timed_mutex对象,调用lock(),try_lock(),try_lock_for(),try_lock_until() 会产生死锁,函数有的会产生Error,有的不会; 若对recursive_mutex和recursive_timed_mutex调用lock(),try_lock(),try_lock_for(),try_lock_until(),将会产生新一级的lock,最后unlock时也需要调用相同数目的unlock方法
-
Locks
Locks提供了一种管理mutex的机制
- lock_guard
-
- 是一种简单的机制,仅提供构造器和析构器方法
-
- 创建时自动上锁,lock_guard析构时自动调用unlock方法
- unique_lock
-
- 相对lock_guard来说,unique_lock更加灵活。创建时自动对mutex对象上锁,析构时自动调用unlock()方法。unique_lock并不管理mutex对象的生命周期,但是mutex对象在lock_guard析构时必须存在。
-
- 支持多种形式的构造器,包括初始化以及移动构造
-
- 支持lock(),try_lock(),try_lock_for(),try_lock_until(),unlock()方法
-
- 支持移动赋值 unique_lock& operator= (unique_lock&& x) noexcept;
-
- swap()方法:交换管理的mutex对象和owning state(lock or unlock)
-
- release()方法:mutex_type* release() noexcept; 返回指向管理的mutex_type的指针,并且unique_lock释放对mutex 对象的管理权,此后unique_lock不再管理任何mutex 对象
-
- owns_lock():返回是否lock住某个mutex对象
-
- (): 与owns_lock()功能相同
-
- mutex(): 返回指向管理的mutex对象的指针
- Other Type
- Functions
-
- lock()
-
-
template <class Mutex1, class Mutex2, class… Mutexes>
void lock (Mutex1& a, Mutex2& b, Mutexes&… cde);
-
-
- lock 所有Mutex对象,但并不按照特定顺序,若暂时无法lock则将block调用线程
-
- 函数返回时保证所有Mutex对象均以被lock,且无死锁产生
-
- 若由于exception导致无法lock某Mutex对象,函数在fail前将首先unlock所有已被lock的Mutex对象
-
- try_lock()
-
- template <class Mutex1, class Mutex2, class… Mutexes> int try_lock (Mutex1& a, Mutex2& b, Mutexes&… cde);
-
- 按照顺序依次尝试lock Mutex对象a,b,…,cde直到所有Mutex对象均lock成功或者任一Mutex 对象lock失败(return false or throw exception)。若失败,则将会对所有已经成功lock的Mutex对象执行unlock操作
- call_once()
-
-
template <class Fn, class… Args>
void call_once (once_flag& flag, Fn&& fn, Args&&… args);
-
-
-
该函数为Passive调用,任意线程调用任意fn,若flag相同,则仅做一次调用。
call_once实例
-
#include <iostream> // std::cout
#include <thread> // std::thread, std::this_thread::sleep_for
#include <chrono> // std::chrono::milliseconds
#include <mutex> // std::call_once, std::once_flag
using namespace::std;
int winner;
void set_winner(int x) { cout << "Enter into set_winner" << endl; winner = x; }//仅执行一次
void print_winner(int x) { cout << "Enter into print_winner" << endl; winner = x; }
std::once_flag winner_flag;
void wait_1000ms(int id) {
// count to 1000, waiting 1ms between increments:
for (int i = ; i<; ++i)
std::this_thread::sleep_for(std::chrono::milliseconds());
// claim to be the winner (only the first such call_once on winner_flag is executed):
std::call_once(winner_flag, set_winner, id);
std::call_once(winner_flag, print_winner, );//will not execute since winner_flag has been called by call_once
}
int main()
{
std::thread threads[];
// spawn 10 threads:
for (int i = ; i<; ++i)
threads[i] = std::thread(wait_1000ms, i + );
std::cout << "waiting for the first among 10 threads to count 1000 ms...\n";
for (auto& th : threads) th.join();
std::cout << "winner thread: " << winner << '\n';
this_thread::sleep_for(chrono::seconds());
cout << "call_once after Sleep" <<endl;
thread t(wait_1000ms, );
t.join();
cout << "New winner " << winner << endl;//the winner result are always same as before
system("pause");
return ;
}
可能的运行结果
waiting for the first among threads to count ms...
Enter into set_winner
winner thread:
call_once after Sleep
New winner
Press any key to continue . . .