- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我看到有人讨厌 recursive_mutex
:
http://www.zaval.org/resources/library/butenhof1.html
但是当考虑如何实现一个线程安全的类(互斥保护)时,在我看来很难证明每个应该受互斥保护的方法都是互斥保护的,并且互斥最多被锁定一次。
所以对于面向对象的设计,应该 std::recursive_mutex
是默认的,而 std::mutex
在一般情况下被认为是一种性能优化,除非它只用于一个地点(只保护一种资源)?
为了清楚起见,我说的是一个私有(private)的非静态互斥体。所以每个类实例只有一个互斥体。
在每个公共(public)方法的开头:
{
std::scoped_lock<std::recursive_mutex> sl;
最佳答案
大多数时候,如果您认为需要递归互斥锁,那么您的设计就是错误的,因此绝对不应该是默认设置。
对于具有单个互斥锁保护数据成员的类,互斥锁应锁定在所有 public
成员函数中,并且所有 private
成员函数应假定互斥体已被锁定。
如果一个public
成员函数需要调用另一个public
成员函数,则将第二个一分为二:一个private
实现函数做这项工作,以及一个 public
成员函数,它只是锁定互斥体并调用 private
之一。然后第一个成员函数也可以调用实现函数,而不必担心递归锁定。
例如
class X {
std::mutex m;
int data;
int const max=50;
void increment_data() {
if (data >= max)
throw std::runtime_error("too big");
++data;
}
public:
X():data(0){}
int fetch_count() {
std::lock_guard<std::mutex> guard(m);
return data;
}
void increase_count() {
std::lock_guard<std::mutex> guard(m);
increment_data();
}
int increase_count_and_return() {
std::lock_guard<std::mutex> guard(m);
increment_data();
return data;
}
};
这当然是一个简单的人为示例,但是 increment_data
函数在两个公共(public)成员函数之间共享,每个成员函数都锁定互斥体。在单线程代码中,可以内联到increase_count
,increase_count_and_return
可以调用它,但是在多线程代码中我们不能这样做。
这只是良好设计原则的应用:公共(public)成员函数负责锁定互斥体,并将完成工作的责任委托(delegate)给私有(private)成员函数。
这样做的好处是 public
成员函数只需要处理在类处于一致状态时被调用:互斥锁被解锁,一旦它被锁定,那么所有不变量都成立。如果您互相调用 public
成员函数,那么它们必须处理互斥锁已被锁定且不变量不一定成立的情况。
这也意味着条件变量等待之类的事情将起作用:如果您将递归互斥锁上的锁传递给条件变量,那么(a)您需要使用 std::condition_variable_any
因为 std::condition_variable
不起作用,并且 (b) 只释放了一级锁,所以你可能仍然持有锁,因此死锁,因为触发谓词并执行通知的线程不能获取锁。
我很难想到需要递归互斥锁的场景。
关于c++ - std::mutex 与 std::recursive_mutex 作为类成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14498892/
我需要在一个函数内锁定一个 std::map 和两个 boost::multimaps 的操作,因为我们有线程试图访问该函数(以及映射)。 我计划使用“std::mutex mutex_var”来保护
已关闭。这个问题是 off-topic 。目前不接受答案。 想要改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 已关闭11 年前。 Improve th
或不同的标题: 为什么处置获得的 Mutex 会破坏它? 我有以下代码,真正的代码在几个方法之间产生,并在这个方法休眠的地方做事: bool createdNew; u
如何测量互斥量、信号量或 futex 的延迟?我的意思是两个事件之间的延迟:解锁先前锁定的互斥体和锁定该互斥体。有两种情况:当所有线程/进程都在同一个 CPU 上时(重新调度线程需要多长时间)以及当第
我执行了以下程序,其中我创建了 100 个线程并发执行。请注意这是一个示例程序。我知道下面的程序不需要多线程,但我的目的是测试互斥量。 class ThreadPool{ public:
我有创建多个线程的代码,所有线程都尝试将信息记录在一个文件中我尝试使用互斥锁来登录文件,但是当我使用 Mutex() 和 Mutex(true or false, "name") 对象时,我得到了不同
我正在研究 Rust 示例。有这段代码: fn new(name: &str, left: usize, right: usize) -> Philosopher { Philosopher
我正在实现一个基于 std::queue 的 C++ 消息队列。 因为我需要 popers 在空队列上等待,所以我考虑使用 mutex 进行互斥,并使用 cond 在空队列上挂起线程,就像 glib
在golang中,sync.Mutex Lock和Unlock是usaul操作,但是Lock和defer Unlock的正确顺序是什么? mu.Lock() defer mu.Unlock() 或 d
在 Go 中,我们可以使用: type Data struct { lock *sync.Mutex } 或 type Data struct { lock sync.Mutex
我尝试摆脱代码中的一些 boost 依赖项,转而使用新的 C++11 功能 (Visual Studio 2013)。 在我的一个组件中,我使用了 boost::mutex与 boost::lock_
我正在使用 scoped_lock 和 mutex 来实现 BlockingQueue posted in a different SO question 的一个版本, 但在 boost 中有多个不同
我在互斥锁析构函数中遇到了上述错误。由于错误可能是由于互斥锁在销毁过程中处于锁定状态,所以我创建了一个新的互斥锁类,它继承自 boost:mutex。这是为了确保互斥锁在销毁期间解锁。但是,仍然会出现
今天写了一些代码来测试mutex的性能。 这是 boost(1.54) 版本,在 vs2010 上编译并进行了 O2 优化: boost::mutex m; auto start = boost::c
我不知道我没有做什么,但我根本无法让自己的调试器保存正在调试的应用程序的“Mutex Owned”或“Mutex Free”信息。 如果我按如下方式调用它,CDB 就可以正常工作: cdb -pn
还没有网上的例子来生动地演示这一点。在 http://en.cppreference.com/w/cpp/header/shared_mutex 看到了一个例子但目前还不清楚。有人可以帮忙吗? 最佳答
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我编写了一个小型 Go 库 ( go-patan ),用于收集某些变量的运行最小值/最大值/平均值/标准偏差。我将它与等效的 Java 实现 ( patan ) 进行了比较,令我惊讶的是 Java 实
我想知道这两者之间的区别是什么 boost::timed_mutex _mutex; if(_mutex.timed_lock(boost::get_system_time() + boost::po
我正在尝试将 dyn 特征存储在 Arc>>>> 中,但是由于某种原因它不起作用 use std::sync::{Arc, Mutex}; trait A{} struct B{} impl A fo
我是一名优秀的程序员,十分优秀!