提问人:Amit G. 提问时间:12/27/2021 最后编辑:Amit G. 更新时间:12/27/2021 访问量:688
为了更多的“常量”成员函数的目的而指定类成员互斥锁“可变”是否“正确”?
Is it "correct" to specify class-member mutex 'mutable' for the purpose of much-more 'const' member functions?
问:
在许多情况下,许多成员函数可以指定为“const”——它们不会修改类的任何数据成员......差不多:它们确实锁定/解锁了类互斥锁。在这种情况下,指定互斥锁“可变”是否是一种好做法? ......否则,将无法指定 get_a()、get_b()、get_c()、get_d() 'const'。
--
仅举一个例子。假设 'example' 是一个线程安全类,并且 m_mutex 保护其 get_a()、get_b()、get_c()、get_d() 不修改的共享资源:
#include <mutex>
class example
{
public:
size_t get_a(void) const {
std::lock_guard lck(m_mutex);
return m_str.length() + a;
};
size_t get_b(void) const {
std::lock_guard lck(m_mutex);
return m_str.length() * 2 + a + b;
};
size_t get_c(void) const {
std::lock_guard lck(m_mutex);
return m_str.length() * 4 + a + b;
};
size_t get_d(void) const {
std::lock_guard lck(m_mutex);
return m_str.length() * 8 + a;
};
void modify_something() {
std::lock_guard lck(m_mutex);
if (m_str.length() < 1000) {
m_str.append(".");
a++;
b++;
}
};
protected:
mutable std::mutex m_mutex;
std::string m_str;
int a = 0, b = 0;
};
答:
2赞
Sneftel
12/27/2021
#1
是的,正是出于这个原因,使同步对象可变是很常见的。话虽如此,在类中保存这些同步对象也相对不常见,因为“确保安全并发”很少是类本身的内容。
评论
0赞
Amit G.
12/27/2021
首先,感谢您的回答。如果您能编辑您的答案并添加一个代码示例,以演示将同步对象保存在类中之外的更好方法,那就太好了。
1赞
Sneftel
12/27/2021
这实际上取决于具体的用例。
5赞
Nikos Athanasiou
12/27/2021
#2
这不仅是正确的,而且是标准做法。成员被描述为“不可观察的非常量”,这意味着它对“用户”观察者来说表现为一个常量。mutex
赫伯·萨特(Herb Sutter)推广了M&M规则:
对于成员变量,可变变量和互斥变量(或原子变量)一起使用。
与您的问题相关的规则部分指出:
对于成员变量,互斥体(或类似的同步类型)意味着可变:本身属于同步类型的成员变量(如互斥体或条件变量)自然希望是可变的,因为您将希望以非常量方式使用它(例如,在并发成员函数中取 )。
std::lock_guard<mutex>
const
链接的文章有许多代码示例和进一步的阐述,如果你想更深入地研究。
下一个:C++ 容器中的逻辑常量
评论