【问题标题】:What's the difference between "mutex" and "lock"?“互斥锁”和“锁”有什么区别?
【发布时间】:2012-03-12 00:47:10
【问题描述】:

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

锁类型

  • 类模板 lock_guard
  • 类模板 unique_lock
  • 类模板 shared_lock
  • 类模板 upgrade_lock
  • 类模板 upgrade_to_unique_lock
  • 互斥体特定类 scoped_try_lock

互斥类型

  • 类互斥体
  • Typedef try_mutex
  • 类 timed_mutex
  • 类 recursive_mutex
  • Typedef recursive_try_mutex
  • 类 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. 或者如果我为 mutex 创建了 shared_lock,这是否意味着互斥锁可以 不能在多个线程之间共享?

【问题讨论】:

  • 您可能会发现我的文章“互斥锁如何工作?”也很有帮助:mortoray.wordpress.com/2011/12/16/…
  • 这些是新问题。你应该在一个新问题中问他们。您不会对已经存在的问题添加后续行动。此外,这些东西都在 Boost 的文档中。

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


【解决方案1】:

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

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

【讨论】:

  • +1:锁的生命周期是独占访问一段代码的持续时间;互斥体的生命周期通常是因为可以锁定的代码段的存在。
【解决方案2】:

互斥锁是一个可以被锁定的对象。锁是对象 维护锁。要创建一个锁,您需要传递一个互斥锁。

【讨论】:

    【解决方案3】:

    锁可以提供互斥但不能提供条件同步。与信号量不同,锁有一个所有者,而所有权很重要 在锁的行为中的作用

    示例 -

    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() 时,在 F() 中执行 mutex.lock(),但调用线程并没有被阻塞,因为它已经拥有 mutex。如果互斥量是二进制信号量而不是锁,那么当在 F() 中执行 mutex.P() 时,从 G() 到 F() 的调用将阻塞调用线程。 (回想一下,二进制信号量上的 P() 和 V() 操作必须交替完成。)这将造成死锁,因为在 F() 或 G() 内没有其他线程能够执行。

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

    【讨论】:

      猜你喜欢
      • 2011-04-13
      • 2010-10-22
      • 2014-09-26
      • 2011-01-20
      • 1970-01-01
      • 2011-08-28
      • 2010-11-06
      • 2018-05-23
      相关资源
      最近更新 更多