一、lock.trylock带参数
lock.trylock
方法是用来获取锁的,比较常用并且非阻塞。如果锁已经被其他线程获取,那么方法直接返回 false
。如果锁没有被其他线程获取,那么方法获取锁并且直接返回 true
。
在 C++11 中,lock.trylock
方法可以传递一个 std::adopt_lock_t
类型的参数,通过这个参数告知方法获取锁并且托管给 std::unique_lock
对象。下面是一个典型的例子:
std::mutex m;
std::unique_lock<std::mutex> lock(m, std::try_to_lock);
if (lock.owns_lock()) {
// ...
}
在上面的例子中,unique_lock
对象会尝试获取锁,如果获取成功,那么该对象会托管 std::mutex
对象并且进行使用。
二、lock.trylock三个参数
在 C++11 中,lock.trylock
方法也可以传递三个参数。下面是三个参数的含义:
lock.trylock(m)
:尝试获取锁,如果锁已经被其他线程获取,那么方法直接返回false
。lock.trylock(m, std::defer_lock)
:创建unique_lock
对象但不获取锁。lock.trylock(m, std::try_to_lock)
:尝试获取锁,如果锁已经被其他线程获取,那么方法直接返回false
。 在以上三个参数中,std::defer_lock
是最常用的。下面是一个典型的例子:
std::mutex m;
std::unique_lock<std::mutex> lock(m, std::defer_lock);
if (lock.try_lock()) {
// ...
}
在上面的例子中,unique_lock
对象不会尝试获取锁。当 unique_lock
对象调用 try_lock
方法时,对象会尝试获取锁。
三、lock.trylock后再lock会报错吗
在 C11 和 C17 中,lock.trylock
获取锁后,如果锁已经被其他线程获取,那么方法会直接返回 false
而不是阻塞调用线程。因此,在获取锁前没有任何问题。
每个线程在获取锁后,需要在规定的时候释放锁。在释放锁前,不能再次锁定相同的锁。下面是一个例子:
std::mutex m;
std::unique_lock<std::mutex> lock(m);
if (lock.try_lock()) {
// ...
lock.unlock();
}
lock.lock(); //会报错
在上面的例子中,unique_lock
对象首先尝试获取锁并且成功,然后执行一些代码,最后释放锁。但是在释放锁后,该线程又再次尝试获取相同的锁。这时候会产生死锁。