在 C++ 中,使用 unique_lock 与 timed_mutex 是一种灵活的锁定机制,它允许你延迟锁定、尝试锁定以及手动控制锁定和解锁。当你创建一个 unique_lock<timed_mutex> 对象时,你可以通过构造函数的参数来控制锁定行为。在析构时自动解锁。
unique_lock<timed_mutex> lg(mtx, defer_lock); 这行代码做了以下几件事:
①创建了一个 unique_lock<timed_mutex> 对象 lg,lg 与 timed_mutex 对象 mtx 关联。
②使用 defer_lock 参数告诉 unique_lock 构造函数不要立即锁定 mtx,这意味着 mtx 在 lg 被创建时不会被锁定,你可以稍后手动调用 lock、try_lock 或 try_lock_for 等方法来锁定它,defer_lock 是一个特殊的锁定策略,它允许你延迟锁定操作,这在某些场景下很有用,比如当你需要在构造函数中执行其他操作后再锁定互斥量,或者当你需要在多个条件满足后才尝试锁定。
一旦你创建了 lg,你可以根据需要使用它的成员函数来控制锁定:
lg.lock():尝试锁定 mtx。如果 mtx 已经被其他线程锁定,当前线程会阻塞,直到 mtx 可用。
lg.try_lock():尝试立即锁定 mtx,而不会阻塞。如果 mtx 可用,则锁定它并返回 true;否则,立即返回 false。
lg.try_lock_for(chrono::duration):尝试在指定的时间段内锁定 mtx。如果在这段时间内 mtx 变得可用并被锁定,则返回 true;否则,返回 false。
注意,当 unique_lock 对象 lg 离开其作用域或被销毁时,它会自动解锁与之关联的 mtx(如果 mtx 已经被锁定)。这有助于确保异常安全,并减少因忘记解锁而导致的死锁风险。
#include <iostream>
#include <thread>
#include <memory>
#include <mutex>
using namespace std;
int shared_data = 0;
timed_mutex mtx;
void func() {
for (int i = 0; i < 2; i++) {
unique_lock<timed_mutex> lg(mtx, defer_lock);
if(lg.try_lock_for(chrono::seconds(2))){//尝试加锁,如果2秒后还没加锁成功,返回false
this_thread::sleep_for(chrono::seconds(1));//对shared_data进行++后,延迟一秒再解锁
shared_data++;
}
}
}
int main() {
thread t1(func);
thread t2(func);
t1.join();
t2.join();
cout << shared_data << endl;
return 0;
}