多线程中的互斥锁

互斥量mutex

类对象,理解成一把锁,多个线程尝试用lock()成员函数来对其加锁,只有一个线程能够锁定成功

lock( ) 与unlock( )须成对存在,很容易出问题, 所以引入**std::lock_guard()**类模板,对于忘记添加unlock(),会自动添加,类似于智能指针的功能。

锁住的代码量多少成为粒度的粗细,粒度越细,代码执行效率越高。

死锁

至少有两个互斥量(锁头)才会产生死锁。避免方法:只要保证互斥量上锁的顺序一致就不会产生死锁。

std::.lock()处理多个互斥量才派的上用场。【谨慎使用】

adopt_lock是一个结构体对象,起一个标记作用:表示互斥量已经lock(),不需要在std::lock_guard<std::mutex> mguard(m_mutex1)再次lock();

// 方法1:
m_mutex2.lock();
m_mutex1.lock();
//---------------
m_mutex2.unlock();
m_mutex1.unlock();
//-------------
m_mutex2.lock();  // 与前面上锁顺序一致
m_mutex1.lock();
//---------------
m_mutex2.unlock();
m_mutex1.unlock();

//  方法2:
std::lock_guard<std::mutex> mguard1(m_mutex1);
std::lock_guard<std::mutex> mguard2(m_mutex2);
//------------------------------
std::lock_guard<std::mutex> mguard1(m_mutex1);
std::lock_guard<std::mutex> mguard2(m_mutex2);

// 方法3:结合std::lock()和lock_guard(),使用adop_lock
std::lock(m_mutex1, m_mutex2);
std::lock_guard<std::mutex> mguard1(m_mutex1, std::adopt_lock);
std::lock_guard<std::mutex> mguard2(m_mutex2, std::adopt_lock);
// 后面无须再unlock();

unique_lock可以完全取代lock_guard

工作中一般使用lock_guard

unique_lock比lock_guard灵活,内存占用多一点

第二个参数:

  • adopt_lock:用之前先lock()
  • try_to_lock:不能先lock(),尝试加锁,用mguard.owns_lock()判断是否加锁成功
  • defer_lock:不能先lock(),初始化一个没有加锁的mutex对象,而后用mguard.lock()加锁
std::unique_lock<std::mutex> mguard(m_mutex, std::defer_lock);

unique_lock的成员函数:

  • lock()
  • unlock()
  • try_lock():尝试加锁返回布尔值,类似于mguard.owns_lock()
  • release():返回管理的mutex对象指针,并释放所有权,即unique_lock与mutex不载有关系。
std::unique_lock<std::mutex> mguard(m_mutex);
std::mutex* pt = mguard.release(); // 此时pt相当于m_mutex,解除关联,有责任手动解锁
//--------------------
pt->unlock();

unique_lock所有权的传递

std::unique_lock<std::mutex> mguard1(m_mutex);
std::unique_lock<std::mutex> mguard2(std::move(mguard1));

猜你喜欢

转载自blog.csdn.net/fly_wt/article/details/101214509
今日推荐