C++11中有一个区域锁lock_guard,还有第二个区域锁unique_lock。
区域锁lock_guard使用起来比较简单,除了构造函数外没有其他member function,在整个区域都有效。
区域锁unique_guard除了lock_guard的功能外,提供了更多的member_function,相对来说更灵活一些。
unique_guard的最有用的一组函数为:
locks the associated mutex (public member function) | |
tries to lock the associated mutex, returns if the mutex is not available (public member function) | |
attempts to lock the associated TimedLockable mutex, returns if the mutex has been unavailable for the specified time duration (public member function) | |
tries to lock the associated TimedLockable mutex, returns if the mutex has been unavailable until specified time point has been reached (public member function) | |
unlocks the associated mutex |
C++11std::unique_lock与std::lock_guard的区别及多线程应用实例
C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为。通常的做法是在修改共享数据成员的时候进行加锁--mutex。在使用锁的时候通常是在对共享数据进行修改之前进行lock操作,在写完之后再进行unlock操作,进场会出现由于疏忽导致由于lock之后在离开共享成员操作区域时忘记unlock,导致死锁。
针对以上的问题,C++11中引入了std::unique_lock与std::lock_guard两种数据结构。通过对lock和unlock进行一次薄的封装,实现自动unlock的功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
std::mutex mut;
void
insert_data()
{
std::lock_guard<std::mutex> lk(mut);
queue.push_back(data);
}
void
process_data()
{
std::unqiue_lock<std::mutex> lk(mut);
queue.pop();
}</std::mutex></std::mutex>
|
通过实现一个线程安全的队列来说明两者之间的差别。
1
2
3
4
5
6
7
8
9
10
11
12
|
template <typename t=
""
>
class
ThreadSafeQueue{
public
:
void
Insert(T value);
void
Popup(T &value);
bool Empety();
private
:
mutable std::mutex mut_;
std::queue<t> que_;
std::condition_variable cond_;
};</t></typename>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
template <typename t=
""
>
void
ThreadSafeQueue::Insert(T value){
std::lock_guard<std::mutex> lk(mut_);
que_.push_back(value);
cond_.notify_one();
}
template <typename t=
""
>
void
ThreadSafeQueue::Popup(T &value){
std::unique_lock<std::mutex> lk(mut_);
cond_.wait(lk, [
this
]{
return
!que_.empety();});
value = que_.front();
que_.pop();
}
template <typename t=
""
>
bool ThreadSafeQueue::Empty()
const
{
std::lock_guard<std::mutex> lk(mut_);
return
que_.empty();
}</std::mutex></typename></std::mutex></typename></std::mutex></typename>
|
上面代码中
1
|
cond_.wait(lk, [
this
]{
return
!Empety();});
|
1
|
[
this
]{
return
!Empety();}
|
还存在另一种读写锁,但是并没有引入C++11,但是boost库提供了对应的实现。读写锁主要适合在于共享数据更新频率较低,但是读取共享数据频率较高的场合。