假设我有一个可能会或可能不会产生多个线程的应用程序.是否有必要保护需要与std :: mutex有条件同步的操作,如下所示,或者锁是如此便宜以至于单线程时无关紧要?
#include <atomic>
#include <mutex>
std::atomic<bool> more_than_one_thread_active{false};
void operation_requiring_synchronization() {
//...
}
void call_operation_requiring_synchronization() {
if (more_than_one_thread_active) {
static std::mutex mutex;
std::lock_guard<std::mutex> lock(mutex);
operation_requiring_synchronization();
} else {
operation_requiring_synchronization();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
感谢所有回答和评论的人,非常有趣的讨论.
几点澄清:
应用程序处理输入块,并为每个块决定是以单线程还是并行或以其他方式并发方式处理它.不需要多线程是不可能的.
在operation_requiring_synchronization()通常由几个插入到全球标准集装箱.
当应用程序独立于平台并且应该在各种平台和编译器(过去,现在和将来)下运行良好时,分析当然是困难的.
根据目前为止的讨论,我倾向于认为优化是值得的.
我也认为std::atomic<bool> more_than_one_thread_active应该将其改为非原子的bool multithreading_has_been_initialized.最初的想法是当除了主要线程以外的所有线程都处于休眠状态时能够再次关闭标志,但我知道这可能是容易出错的.
将显式条件抽象为定制的lock_guard是一个好主意(并且有助于设计的未来变化,包括如果不认为优化值,则简单地恢复到std :: lock_guard).
考虑以下代码:
struct A {
double d;
float a;
};
static_assert(sizeof(A) == 2 * sizeof(double), "");
struct B : A {
float b;
};
static_assert(sizeof(B) == sizeof(A), ""); //Fails
struct C {
A a;
float b;
};
static_assert(sizeof(C) == sizeof(A), ""); //Fails
Run Code Online (Sandbox Code Playgroud)
有没有(最好是便携式)方式来安排b住在A的未使用的拖尾填充空间?
我可以通过在末尾添加一个预期数据成员来修改A,或者我可以将b构建到A的填充空间中,但必须有更好的方法来做到这一点.
也许pragma pack(但A的多个数据成员应该保持对齐而不是压缩)?或者正确放置的对齐?