我能否使 C++11 类/对象通用线程安全?
Can I make a C++11 class/object universally thread safe?
阅读了互斥实现可以互换(独立于线程实现)后,我的理解是,通过使用C++ 11 个互斥体,我可以确保我的类对所有线程实现都是线程安全的。
我的理解正确吗?我期待是(也许有警告)或否(有理由)。
- 我的代码可能需要在目标平台上重新编译,但不需要对我的源代码进行任何更改。(@Peter)
- 或者说,我应该能够针对特定平台进行编译并提供一个可以安全地与任何线程库一起使用的 .?
鉴于反对票,我将尽量更准确。
互斥锁的 C++11 实现是否独立于任何其他线程 API?C++11 互斥锁是否只知道彼此并独立于执行线程如何到达该点而实现阻塞。
C++11 互斥锁是否始终适用于 OpenMP(带重新编译)?团队 A 能否提供线程安全 API(使用 C++ 互斥体)供团队 B 使用,而不管团队 B 使用的特定线程 API?所有代码都可以重新编译。
我附上一个工作示例。
#include <iostream>
#include <omp.h>
#include <mutex>
class A {
unsigned n = 0;
public:
void inc() {
++n;
}
unsigned get() {
return n;
}
};
class B {
std::mutex mutex;
unsigned n = 0;
public:
void inc() {
mutex.lock();
++n;
mutex.unlock();
}
unsigned get() {
return n;
}
};
int main() {
A a;
B b;
#pragma omp parallel for
for (int i = 0; i < 100000; i++) {
a.inc();
b.inc();
}
std::cout << a.get() << " " << b.get() << std::endl;
}
我上次运行的输出是:
98015 100000
这是运气还是设计?
如果将所有成员设为私有,并且对受任何同步机制(std::mutex
、std::atomic
或其他受 boost/Qt/其他保护的数据进行所有访问(读/写)操作,则无论使用何种线程 API,都可以使类独立于线程平台。
最简单的方法是对类内的所有数据访问操作(getter/setter)使用单个std::recursive_mutex
/std::unique_lock
对,并使数据成员私有。无论线程 API 如何,它都可以保证工作,但可能不是最佳的性能。
大多数其他解决方案可能适合或不适合您的具体情况。有时根本不需要同步原语。
您始终可以使用互斥体使类的成员函数在没有数据争用的情况下进行交互。但这还不足以确保可以从多个线程使用一个对象而不会发生冲突;您需要更广泛的设计。例如,考虑写出向量的内容:
int size = vec.size();
for (int i = 0; i < size; ++i)
std::cout << vec[i] << ' ';
std::cout << 'n';
使用内部互斥锁,对vec.size()
的调用和对vec::operator[]
的调用没有数据争用,因此从多个线程调用它们是"安全的"。但是这段代码有一个问题:如果另一个线程从向量中删除一个元素,那么向量将比原来小,并且这个循环将从末尾运行。
- 如何将元素添加到数组的线程安全函数?
- C++中的线程安全删除
- 在std::thread中,joinable()然后join()线程安全吗
- 在c++队列中使用pop和visit实现线程安全
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 全局变量 多读取器 一个写入器多线程安全?
- 共享队列的线程安全
- boost::文件系统::recursive_directory_iterator多线程安全
- 以线程安全的方式转换 C/C++ 中时区名称字符串的时区偏移量
- 线程安全运算符<<
- 如何使缓存线程安全
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 提升精神 V2 Qi 语法线程安全吗?
- asio 链对象线程安全吗?
- 线程安全队列 c++
- 提供对不同类型的数据(建议、代码审查)的线程安全访问的类
- 如何以线程安全的方式更改目录?
- 线程安全的引用计数队列C++
- 析构函数和线程安全
- 适用于大型数组的无复制线程安全环形缓冲区