“互斥”和“锁定”有什么区别?

时间:2012-02-21 17:24:29

标签: c++ multithreading boost mutex boost-thread

我对锁和互斥锁之间的区别感到非常困惑。在Boost文档中,它说,

锁定类型

  • 班级模板lock_guard
  • 类模板unique_lock
  • 班级模板shared_lock
  • 班级模板upgrade_lock
  • 班级模板upgrade_to_unique_lock
  • 特定于互斥锁的类scoped_try_lock

互斥锁类型

  • Class mutex
  • Typedef try_mutex
  • 类timed_mutex
  • Class recursive_mutex
  • Typedef recursive_try_mutex
  • Class recursive_timed_mutex
  • 类shared_mutex

在另一篇文章中,我看到了这样的函数,

boost::shared_mutex _access;
void reader()
{
  boost::shared_lock< boost::shared_mutex > lock(_access);
  // do work here, without anyone having exclusive access
}    
void conditional_writer()
{
  boost::upgrade_lock< boost::shared_mutex > lock(_access);
  // do work here, without anyone having exclusive access

  if (something) {
    boost::upgrade_to_unique_lock< boost::shared_mutex > uniqueLock(lock);
    // do work here, but now you have exclusive access
  }
  // do more work here, without anyone having exclusive access
}

更新了问题

  1. 任何人都可以在“互斥”和“锁定”之间作出一些澄清吗?
  2. 是否有必要为 shared_mutex 创建 shared_lock ? 如果我为 shared_mutex 创建 unique_lock ,会发生什么?
  3. 或者如果我为互斥锁创建 shared_lock ,是否意味着互斥锁可以 不能在多个线程之间共享?

3 个答案:

答案 0 :(得分:37)

互斥锁是同步对象。您在代码段的开头获取互斥锁,并在最后释放它,以确保没有其他线程同时访问相同的数据。互斥锁通常具有与其保护的数据相同的生命周期,并且多个线程可以访问一个互斥锁。

锁定对象是封装该锁的对象。构造对象时,它获取互斥锁上的锁。当它被破坏时,锁被释放。您通常会为每次访问共享数据创建一个新的锁定对象。

答案 1 :(得分:11)

互斥锁是可以锁定的对象。锁是对象 保持锁定。要创建锁,您需要将其传递给互斥锁。

答案 2 :(得分:1)

锁定可以提供互斥而不是条件同步。与信号量不同,锁具有所有者,所有权起着重要作用 锁定行为中的角色

示例 -

class lockableObject { public void F() {
mutex.lock(); ...; mutex.unlock();
}
public void G() {
mutex.lock(); ...; F(); ...; mutex.unlock();
}
private mutexLock mutex; }
// method G() calls method F()

类lockableObject中的锁定互斥锁用于将方法F()和G()转换为关键部分。因此,一次只能有一个线程在lockableObject的方法内执行。当线程调用方法G()时,互斥锁被锁定。当方法G()调用方法F()时,mutex.lock()在F()中执行,但调用线程没有被阻塞,因为它已经拥有了互斥锁。如果互斥锁是二进制信号量而不是锁,则在F()中执行mutex.P()时,从G()到F()的调用将阻塞调用线程。 (回想一下,对二进制信号量的P()和V()操作的补充必须交替。)这会产生死锁,因为没有其他线程能够在F()或G()内执行。

这些是锁和二进制信号量之间的差异: 1对于二进制信号量,如果对P()进行两次调用而没有对V()的任何干预,则第二次调用将阻塞。但是,拥有锁并再次请求所有权的线程不会被阻止。 (请注意锁定并不总是递归的,因此在使用锁之前请检查文档。) 2连续调用lock()和unlock()的所有者必须是同一个线程。但是对P()和V()的连续调用可以由不同的线程进行。